// 模拟考试数据 (实际项目中从后端获取)
let MOCK_EXAMS = [
    {
        id: 1,
        exam_name: '期中数学考试',
        subject: '数学',
        exam_time: '2024-05-20T09:00',
        location: '教学楼A-101',
        description: '八年级下学期期中考试',
        create_time: '2024-05-01T10:00:00Z',
        update_time: '2024-05-02T11:00:00Z'
    },
    {
        id: 2,
        exam_name: '期末英语测试',
        subject: '英语',
        exam_time: '2024-06-15T14:30',
        location: '综合楼B-203',
        description: '八年级下学期期末综合能力测试',
        create_time: '2024-06-01T08:00:00Z',
        update_time: '2024-06-01T09:00:00Z'
    }
];

let nextExamId = MOCK_EXAMS.length > 0 ? Math.max(...MOCK_EXAMS.map(e => e.id)) + 1 : 1;

// 模拟学生数据
let MOCK_STUDENTS = [
    { id: 1, stu_no: 'S001', name: '张三', gender: '男', class_id: 1, phone: '13800138001', create_time: '2023-09-05T10:00:00Z', update_time: '2023-09-05T10:00:00Z' },
    { id: 2, stu_no: 'S002', name: '李四', gender: '女', class_id: 1, phone: '13900139002', create_time: '2023-09-05T10:05:00Z', update_time: '2023-09-05T10:05:00Z' },
    { id: 3, stu_no: 'S003', name: '王五', gender: '男', class_id: 2, phone: '13700137003', create_time: '2023-09-05T10:10:00Z', update_time: '2023-09-05T10:10:00Z' }
];
let nextStudentId = MOCK_STUDENTS.length > 0 ? Math.max(...MOCK_STUDENTS.map(s => s.id)) + 1 : 1;

// 模拟成绩数据
let MOCK_GRADES = [
    { id: 1, student_id: 1, exam_id: 1, score: 85, create_time: '2024-05-21T10:00:00Z', update_time: '2024-05-21T10:00:00Z' },
    { id: 2, student_id: 2, exam_id: 1, score: 92, create_time: '2024-05-21T10:05:00Z', update_time: '2024-05-21T10:05:00Z' },
    { id: 3, student_id: 1, exam_id: 2, score: 78, create_time: '2024-06-16T09:00:00Z', update_time: '2024-06-16T09:00:00Z' },
    { id: 4, student_id: 3, exam_id: 1, score: 88, create_time: '2024-05-21T10:10:00Z', update_time: '2024-05-21T10:10:00Z' }
];
let nextGradeId = MOCK_GRADES.length > 0 ? Math.max(...MOCK_GRADES.map(g => g.id)) + 1 : 1;

// +++++ NEW HELPER FUNCTIONS FOR POPULATING DROPDOWNS FROM API +++++

async function populateExamFilterDropdown(selectElementId, includeAllOption = true) {
    const selectElement = document.getElementById(selectElementId);
    if (!selectElement) {
        console.error(`Dropdown element with ID ${selectElementId} not found.`);
        return;
    }

    try {
        const exams = await fetchApi('/exams');
        selectElement.innerHTML = ''; 

        if (includeAllOption) {
            const allOption = document.createElement('option');
            allOption.value = '';
            allOption.textContent = '所有考试';
            selectElement.appendChild(allOption);
        }

        if (exams && exams.length > 0) {
            exams.forEach(exam => {
                const option = document.createElement('option');
                option.value = exam.id; 
                option.textContent = exam.examName || `考试ID: ${exam.id}`;
                selectElement.appendChild(option);
            });
        } else if (!includeAllOption && exams && exams.length === 0) {
             const noOption = document.createElement('option');
             noOption.value = '';
             noOption.textContent = '暂无考试可选';
             selectElement.appendChild(noOption);
        }
    } catch (error) {
        console.error(`Error populating exam dropdown ${selectElementId}:`, error);
        selectElement.innerHTML = '<option value="">加载失败</option>';
        showAdminToast(`加载考试列表失败: ${error.message}`, 'error');
    }
}

async function populateClassFilterDropdown(selectElementId, includeAllOption = true) {
    const selectElement = document.getElementById(selectElementId);
    if (!selectElement) {
        console.error(`Dropdown element with ID ${selectElementId} not found.`);
        return;
    }

    try {
        const classes = await fetchApi('/classes');
        selectElement.innerHTML = '';

        if (includeAllOption) {
            const allOption = document.createElement('option');
            allOption.value = '';
            allOption.textContent = '所有班级';
            selectElement.appendChild(allOption);
        }

        if (classes && classes.length > 0) {
            classes.forEach(cls => {
                const option = document.createElement('option');
                option.value = cls.id; 
                option.textContent = cls.className || `班级ID: ${cls.id}`; //
                selectElement.appendChild(option);
            });
        } else if (!includeAllOption && classes && classes.length === 0) {
            const noOption = document.createElement('option');
            noOption.value = '';
            noOption.textContent = '暂无班级可选';
            selectElement.appendChild(noOption);
       }
    } catch (error) {
        console.error(`Error populating class dropdown ${selectElementId}:`, error);
        selectElement.innerHTML = '<option value="">加载失败</option>';
        showAdminToast(`加载班级列表失败: ${error.message}`, 'error');
    }
}

async function populateStudentDropdownForForm(selectElementId) {
    const selectElement = document.getElementById(selectElementId);
    if (!selectElement) {
        console.error(`Dropdown element with ID ${selectElementId} not found for grade form.`);
        return;
    }

    selectElement.innerHTML = ''; // Clear existing options first

    try {
        const studentPage = await fetchApi('/students/page?page=1&pageSize=10000');
        const students = studentPage && studentPage.records ? studentPage.records : [];

        if (students.length > 0) {
            // Add the default "请选择学生" option first, which is required to be changed
            const defaultOption = document.createElement('option');
            defaultOption.value = ""; // Empty value will fail 'required' validation if selected
            defaultOption.textContent = "请选择学生...";
            selectElement.appendChild(defaultOption);

            students.forEach(student => {
                const option = document.createElement('option');
                option.value = student.id; 
                option.textContent = `${student.name || '未知姓名'} (${student.stuNo || 'N/A'})`;
                selectElement.appendChild(option);
            });
        } else {
            // No students: add a disabled, selected placeholder option.
            // The 'required' attribute on select will trigger validation correctly.
            const noStudentOption = document.createElement('option');
            noStudentOption.value = ""; // Value is empty, so it won't satisfy 'required'
            noStudentOption.textContent = "暂无学生可选";
            noStudentOption.disabled = true;
            noStudentOption.selected = true;
            selectElement.appendChild(noStudentOption);
        }
    } catch (error) {
        console.error(`Error populating student dropdown for form ${selectElementId}:`, error);
        // Fallback if API fails: also provide a disabled, selected placeholder
        selectElement.innerHTML = ''; // Clear again
        const errorOption = document.createElement('option');
        errorOption.value = "";
        errorOption.textContent = "加载学生失败";
        errorOption.disabled = true;
        errorOption.selected = true;
        selectElement.appendChild(errorOption);
        showAdminToast(`加载学生列表失败 (表单): ${error.message}`, 'error');
    }
}

async function populateExamDropdownForForm(selectElementId) {
    const selectElement = document.getElementById(selectElementId);
    if (!selectElement) {
        console.error(`Dropdown element with ID ${selectElementId} not found for grade form.`);
        return;
    }
    try {
        const exams = await fetchApi('/exams');
        selectElement.innerHTML = '<option value="">请选择考试</option>'; 

        if (exams && exams.length > 0) {
            exams.forEach(exam => {
                const option = document.createElement('option');
                option.value = exam.id;
                option.textContent = exam.examName || `考试ID: ${exam.id}`;
                selectElement.appendChild(option);
            });
        } else {
            selectElement.innerHTML = '<option value="">暂无考试可选</option>';
        }
    } catch (error) {
        console.error(`Error populating exam dropdown for form ${selectElementId}:`, error);
        selectElement.innerHTML = '<option value="">加载考试失败</option>';
        showAdminToast(`加载考试列表失败 (表单): ${error.message}`, 'error');
    }
}

// ----- END OF NEW HELPER FUNCTIONS -----

// ===================================================================================
// 全局辅助函数 (确保这些在顶部定义)
// ===================================================================================
// API_BASE_URL 和 logout() 假设由 auth.js 提供并已在 admin.html 中先于 admin.js 引入

function formatDateTime(dateTimeStr) {
    if (!dateTimeStr) return 'N/A';
    try {
        const date = new Date(dateTimeStr);
        if (dateTimeStr.includes('T') && (dateTimeStr.includes('Z') || dateTimeStr.match(/[+-]\d{2}:\d{2}$/))) { // Check for ISO format
             return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' });
        }
        return dateTimeStr; 
    } catch (e) {
        return dateTimeStr; 
    }
}

// 添加 populateClassDropdown 函数
async function populateClassDropdown(selectElement, includeAllOption = true) {
    if (!selectElement) {
        console.error('Select element not found for populateClassDropdown');
        return;
    }

    try {
        const classes = await fetchApi('/classes');
        selectElement.innerHTML = ''; // 清空现有选项

        if (includeAllOption) {
            const allOption = document.createElement('option');
            allOption.value = '';
            allOption.textContent = '所有班级';
            selectElement.appendChild(allOption);
        }

        if (classes && classes.length > 0) {
            classes.forEach(cls => {
                const option = document.createElement('option');
                option.value = cls.id;
                option.textContent = cls.className || `班级ID: ${cls.id}`;
                selectElement.appendChild(option);
            });
        } else if (!includeAllOption && classes && classes.length === 0) {
            const noOption = document.createElement('option');
            noOption.value = '';
            noOption.textContent = '暂无班级可选';
            selectElement.appendChild(noOption);
        }
    } catch (error) {
        console.error('Error populating class dropdown:', error);
        selectElement.innerHTML = '<option value="">加载失败</option>';
        showAdminToast(`加载班级列表失败: ${error.message}`, 'error');
    }
}

function showAdminToast(message, type = 'info', title = '提示') {
    const toastContainer = document.getElementById('toastContainer');
    if (!toastContainer) {
        console.warn('Toast container #toastContainer not found in admin.html');
        alert(`${title}: ${message}`); // Fallback
        return;
    }
    let bgColorClass = 'bg-info';
    let iconHtml = '<i class="fas fa-info-circle mr-2"></i>'; 

    switch (type) {
        case 'success':
            bgColorClass = 'bg-success';
            iconHtml = '<i class="fas fa-check-circle mr-2"></i>';
            title = title === '提示' ? '成功' : title;
            break;
        case 'danger':
        case 'error':
            bgColorClass = 'bg-danger';
            iconHtml = '<i class="fas fa-times-circle mr-2"></i>';
            title = title === '提示' ? '错误' : title;
            break;
        case 'warning':
            bgColorClass = 'bg-warning text-dark';
            iconHtml = '<i class="fas fa-exclamation-triangle mr-2"></i>';
            title = title === '提示' ? '警告' : title;
            break;
    }

    const toastId = 'toast-admin-' + Date.now() + Math.random().toString(36).substring(2,7);
    const toastHTML = `
        <div id="${toastId}" class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-delay="5000">
            <div class="toast-header ${bgColorClass} text-white">
                ${iconHtml}
                <strong class="mr-auto">${title}</strong>
                <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close" style="${(type === 'danger' || type === 'error' || type === 'warning') ? 'color: #fff; text-shadow: none;' : ''}">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="toast-body">
                ${message.replace(/\\n/g, '<br>')}
            </div>
        </div>
    `;
    toastContainer.insertAdjacentHTML('beforeend', toastHTML);
    $('#' + toastId).toast('show').on('hidden.bs.toast', function () {
        $(this).remove();
    });
}

function showTableLoadingSpinner(tableBodyElement, colspan) {
    if (tableBodyElement) {
        tableBodyElement.innerHTML = `<tr><td colspan="${colspan}" class="text-center p-5"><div class="spinner-border text-primary" role="status"><span class="sr-only">加载中...</span></div><p class="mt-2">正在加载数据...</p></td></tr>`;
    }
}

function setButtonLoading(buttonElement, isLoading, loadingText = '处理中...', originalContent = null) {
    if (!buttonElement) return;
    if (isLoading) {
        if (originalContent === null) { 
          buttonElement.dataset.originalHTML = buttonElement.innerHTML; // Store original HTML
        }
        buttonElement.disabled = true;
        buttonElement.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ${loadingText}`;
    } else {
        buttonElement.disabled = false;
        buttonElement.innerHTML = originalContent || buttonElement.dataset.originalHTML || 'Submit'; // Fallback
        if (buttonElement.dataset.originalHTML) {
             delete buttonElement.dataset.originalHTML; // Clean up only if it was set by this function
        }
    }
}

// ===================================================================================
// 全局 API 请求辅助函数
// ===================================================================================
// getToken() 函数需要能从 js/auth.js (或这里) 获取
// 如果 auth.js 是分开的，确保 getToken 在此作用域可用
// 如果上面已在 admin.js 中定义 Token 管理函数，则无需额外操作。

// const TOKEN_KEY = 'jwtToken'; // 如果在 admin.js 中重新定义getToken
// function getToken() {
//     return localStorage.getItem(TOKEN_KEY);
// }

async function fetchApi(endpoint, method = 'GET', body = null, customHeaders = {}) {
    const url = `${API_BASE_URL}${endpoint}`;

    const headers = {
        ...customHeaders
    };

    const token = getToken(); // 从 localStorage 获取 Token
    if (token) {
        headers['Authorization'] = `Bearer ${token}`; // 添加 Authorization 头部
    }

    if (body && (method === 'POST' || method === 'PUT')) {
        headers['Content-Type'] = 'application/json';
    }

    const config = {
        method: method,
        headers: headers
        // credentials: 'include' // 对于 Bearer Token 认证，此项不再是必须的，
                               // 除非您有其他基于Cookie的跨域需求（但我们正试图摆脱它）
                               // 如果没有其他Cookie依赖，可以移除。
    };

    if (body) {
        config.body = JSON.stringify(body);
    }

    try {
        const response = await fetch(url, config);

        if (response.status === 401) { // 对于JWT，401通常意味着Token无效、过期或未提供
            showAdminToast('认证失败或Token已过期，请重新登录。', 'error', '认证失败');
            logout(); // logout 函数会移除 token 并重定向
            throw new Error(`Authentication failed with status ${response.status}`);
        }
        if (response.status === 403) { // 禁止访问 (Token有效，但用户无权限)
            showAdminToast('您没有权限执行此操作。', 'danger', '权限不足');
            // logout(); // 对于403，不一定总是要登出，取决于业务逻辑
            throw new Error(`Authorization failed with status ${response.status}`);
        }
        
        if (!response.ok && response.headers.get("content-type")?.includes("application/json")) {
            const errorData = await response.json().catch(() => ({ message: `服务器返回了错误状态 ${response.status}，但无法解析错误详情。` }));
            const err = new Error(errorData.message || `API request to ${endpoint} failed with status ${response.status}`);
            err.status = response.status;
            err.data = errorData;
            throw err;
        } else if (!response.ok) {
            const errText = await response.text().catch(() => `API request to ${endpoint} failed with status ${response.status} and no error text.`);
            const err = new Error(errText);
            err.status = response.status;
            throw err;
        }
        
        if (response.status === 204) {
            return null; 
        }

        if (response.headers.get("content-type")?.includes("application/json")) {
            return await response.json();
        }
        
        return await response.text();

    } catch (error) {
        if (error.message && (error.message.startsWith('Authentication failed') || error.message.startsWith('Authorization failed'))) {
            console.error("fetchApi: Auth error handled.", error.status ? `Status: ${error.status}` : '', error.message);
            throw error; 
        }
        console.error('fetchApi Error:', error.status ? `Status: ${error.status}` : '', error.message, error.data || '');
        showAdminToast(`请求API (${method} ${endpoint}) 失败: ${error.message}`, 'error', 'API请求错误');
        throw error; 
    }
}

// ===================================================================================
// 班级管理 (Class Management) - 后端对接函数 (定义在全局作用域)
// ===================================================================================
let currentEditingClassId_backend = null; 

function resetClassForm_backend() {
    const classFormEl = document.getElementById('classForm');
    const hiddenClassIdInputEl = document.getElementById('class_id');
    const classModalLabelEl = document.getElementById('classModalLabel');

    if (classFormEl) {
        classFormEl.reset();
        if (hiddenClassIdInputEl) hiddenClassIdInputEl.value = '';
        currentEditingClassId_backend = null;
        classFormEl.classList.remove('was-validated');
        $(classFormEl).find('.is-invalid').removeClass('is-invalid');
        $(classFormEl).find('.is-valid').removeClass('is-valid');
    }
    if (classModalLabelEl) classModalLabelEl.textContent = '新增班级';
}

function validateClassForm_backend() {
    const classFormEl = document.getElementById('classForm');
    if (!classFormEl) return false;
    let isValid = true;
    
    $(classFormEl).find('.is-invalid').removeClass('is-invalid');

    const classNameInput = document.getElementById('class_name');
    const headTeacherInput = document.getElementById('head_teacher');
    const studentCountInput = document.getElementById('student_count');

    if (!classNameInput.value.trim()) {
        $(classNameInput).addClass('is-invalid').siblings('.invalid-feedback').show();
        isValid = false;
    } else {
        $(classNameInput).removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
    }
    if (!headTeacherInput.value.trim()) {
        $(headTeacherInput).addClass('is-invalid').siblings('.invalid-feedback').show();
        isValid = false;
    } else {
        $(headTeacherInput).removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
    }
    
    const studentCountVal = studentCountInput.value.trim();
    if (studentCountVal !== '' && (isNaN(parseInt(studentCountVal)) || parseInt(studentCountVal) < 0)) {
        $(studentCountInput).addClass('is-invalid').siblings('.invalid-feedback').text('学生人数必须是非负整数。').show();
        isValid = false;
    } else if (studentCountVal === '') {
        // Assuming student count can be empty (null), so no validation error if empty
         $(studentCountInput).removeClass('is-invalid is-valid').siblings('.invalid-feedback').hide();
    }
     else {
        $(studentCountInput).removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
    }


    // Use HTML5 built-in validation check as well for other constraints like 'required'
    if (!classFormEl.checkValidity()) { // This will trigger browser's default validation UI for 'required'
        classFormEl.classList.add('was-validated'); // This helps Bootstrap show its own styles
        isValid = false;
    }
    return isValid;
}

async function loadClasses_backend() {
    const classTableBodyEl = document.getElementById('classTableBody');
    if (!classTableBodyEl) {
        console.error("Class table body not found!");
        return;
    }
    showTableLoadingSpinner(classTableBodyEl, 7); 

    try {
        const classes = await fetchApi('/classes'); // 使用 fetchApi
        renderClassTable_backend(classes);
    } catch (error) {
        // fetchApi 会处理 401/403 并调用 logout()
        // 对于其他错误，fetchApi 会显示一个通用的错误提示
        // 如果 loadClasses_backend 仍需处理特定错误，可在此处添加
        console.error('Error loading classes specifically in loadClasses_backend:', error);
        // 如果错误不是因为认证失败（那种情况 fetchApi 已处理），则显示特定于表格的错误
        if (!(error.message && error.message.startsWith('Authentication failed'))) {
             classTableBodyEl.innerHTML = `<tr><td colspan="7" class="text-center text-danger">加载班级数据时发生错误: ${error.message}</td></tr>`;
        }
    }
}

function renderClassTable_backend(classes) {
    const classTableBodyEl = document.getElementById('classTableBody');
    if (!classTableBodyEl) return;
    classTableBodyEl.innerHTML = ''; 

    if (!classes || classes.length === 0) {
        classTableBodyEl.innerHTML = '<tr><td colspan="7" class="text-center">暂无班级数据</td></tr>';
        return;
    }

    classes.forEach(cls => {
        const row = classTableBodyEl.insertRow();
        row.innerHTML = `
            <td>${cls.id}</td>
            <td>${cls.className || 'N/A'}</td>
            <td>${cls.headTeacher || 'N/A'}</td>
            <td>${cls.studentCount !== null && cls.studentCount !== undefined ? cls.studentCount : 'N/A'}</td>
            <td>${cls.createTime ? formatDateTime(cls.createTime) : 'N/A'}</td>
            <td>${cls.updateTime ? formatDateTime(cls.updateTime) : 'N/A'}</td>
            <td class="action-buttons">
                <button class="btn btn-sm btn-info edit-class-btn-backend" title="编辑"><i class="fas fa-edit"></i> 编辑</button>
                <button class="btn btn-sm btn-danger delete-class-btn-backend" title="删除"><i class="fas fa-trash"></i> 删除</button>
            </td>
        `;
        // Pass the full class object to the edit handler
        row.querySelector('.edit-class-btn-backend').addEventListener('click', () => handleEditClassShowModal_backend(cls));
        // Pass ID and name for delete confirmation
        row.querySelector('.delete-class-btn-backend').addEventListener('click', (event) => handleDeleteClass_backend(cls.id, cls.className, event.currentTarget));
    });
}

function handleEditClassShowModal_backend(classObj) { 
    resetClassForm_backend(); // Reset form first
    const hiddenClassIdInputEl = document.getElementById('class_id');
    const classModalLabelEl = document.getElementById('classModalLabel');
    
    currentEditingClassId_backend = classObj.id; 
    if (hiddenClassIdInputEl) hiddenClassIdInputEl.value = classObj.id;
    document.getElementById('class_name').value = classObj.className || '';
    document.getElementById('head_teacher').value = classObj.headTeacher || '';
    document.getElementById('student_count').value = classObj.studentCount !== null && classObj.studentCount !== undefined ? classObj.studentCount : '';
    
    if (classModalLabelEl) classModalLabelEl.textContent = '编辑班级';
    $('#classModal').modal('show');
}

async function handleDeleteClass_backend(classId, className, deleteButton) { // 确保 deleteButton 被传递
    if (!confirm(`确定要删除班级 "${className || 'ID: ' + classId}" 吗？此操作不可恢复。`)) {
        return;
    }
    
    const originalButtonHTML = deleteButton ? deleteButton.innerHTML : null;
    if(deleteButton) setButtonLoading(deleteButton, true, '', originalButtonHTML);

    try {
        await fetchApi(`/classes/${classId}`, 'DELETE'); // 使用 fetchApi
        showAdminToast(`班级 "${className || 'ID: ' + classId}" 删除成功！`, 'success');
        loadClasses_backend(); 
    } catch (error) {
        console.error('Failed to delete class specifically in handleDeleteClass_backend:', error);
        // 通用错误已由 fetchApi 处理并提示, 如果需要特定于删除操作的恢复逻辑，可在此处添加
    } finally {
        if(deleteButton) setButtonLoading(deleteButton, false, '', originalButtonHTML);
    }
}
// ===================================================================================
// END 班级管理函数
// ===================================================================================


document.addEventListener('DOMContentLoaded', function() {
    // 1. 权限检查
    if (!checkAuth('admin')) {
        return; 
    }

    // 2. 显示管理员名称
    const currentUser = getCurrentUser();
    if (currentUser && currentUser.name) {
        const adminNameSpan = document.getElementById('adminName');
        if (adminNameSpan) {
            adminNameSpan.textContent = currentUser.name;
        }
    }

    // 3. 导航链接点击事件处理
    const navLinks = document.querySelectorAll('#adminSidebar .nav-link');
    const mainSections = document.querySelectorAll('.main-section');

    navLinks.forEach(link => {
        link.addEventListener('click', function(event) {
            event.preventDefault();
            const targetId = this.getAttribute('data-target');

            if (this.id === 'logoutButton') {
                logout();
                return;
            }

            navLinks.forEach(nav => nav.classList.remove('active'));
            this.classList.add('active');

            mainSections.forEach(section => {
                section.style.display = 'none';
            });

            if (targetId) {
                const targetSection = document.getElementById(targetId);
                if (targetSection) {
                    targetSection.style.display = 'block';
                    
                    if (targetId === 'class-management-content') {
                        loadClasses_backend(); 
                    } else if (targetId === 'exam-management-content') {
                        loadExams_backend(); 
                    } else if (targetId === 'student-management-content') {
                        populateClassDropdown(document.getElementById('class_id_form')); 
                        populateClassDropdown(document.getElementById('filterClassIdStudents'), true); 
                        loadStudents_backend(1); // 自动加载第一页学生数据
                    } else if (targetId === 'grade-management-content') {
                        loadGrades_backend(); 
                        
                        populateExamFilterDropdown('filterExamId', true); 
                        populateClassFilterDropdown('filterClassIdGrades', true); 

                        // Populate dropdowns for the grade modal (add/edit form)
                        populateExamDropdownForForm('grade_exam_id');   
                        
                        const gradeFilterForm = document.getElementById('gradeFilterForm');
                        if (gradeFilterForm) gradeFilterForm.reset();
                        const gradeStatsContainer = document.getElementById('gradeStatsContainer');
                        if (gradeStatsContainer) gradeStatsContainer.innerHTML = '';
                        // renderGradeTable(); // 这个是旧的mock渲染函数，已被loadGrades_backend替代
                    }
                }
            }
        });
    });

    // 4. 侧边栏切换 (针对小屏幕)
    const sidebar = document.getElementById('adminSidebar');
    const sidebarCollapseButton = document.getElementById('sidebarCollapse');
    if (sidebar && sidebarCollapseButton) {
        sidebarCollapseButton.addEventListener('click', function() {
            sidebar.classList.toggle('toggled');
        });
    }

    // 5. 默认激活仪表盘并加载对应内容
    const dashboardLink = document.querySelector('#adminSidebar .nav-link[data-target="dashboard-content"]');
    if (dashboardLink) {
        dashboardLink.click(); 
    } else { // Fallback if dashboard link isn't there, try to activate the first available link or class management
        const firstVisibleNavLink = document.querySelector('#adminSidebar .nav-link:not(#logoutButton)');
        if (firstVisibleNavLink) {
            firstVisibleNavLink.click(); // Activate the first link
        } else { // If nothing else, and class management exists, try to load it
             if (document.getElementById('class-management-content')) {
                loadClasses_backend();
             }
        }
    }
    
    // ===================================================================================
    // 班级管理模块事件绑定 (在 DOMContentLoaded 内)
    // ===================================================================================
    const addClassBtn_el_dom = document.getElementById('addClassBtn');
    const saveClassBtn_el_dom = document.getElementById('saveClassBtn');
    // const classForm_el_dom = document.getElementById('classForm'); // 已在 reset/validate 中使用

    if (addClassBtn_el_dom) {
        addClassBtn_el_dom.addEventListener('click', function() {
            resetClassForm_backend(); 
        });
    }

    if (saveClassBtn_el_dom) { // classForm_el_dom 检查已移至 validateClassForm_backend
        saveClassBtn_el_dom.addEventListener('click', async function() {
            if (!validateClassForm_backend()) {
                showAdminToast('请检查表单，确保所有必填项都已正确填写，且格式正确。', 'warning', '表单无效');
                return;
            }

            const hiddenClassIdInputEl_dom = document.getElementById('class_id');
            const classId = hiddenClassIdInputEl_dom ? hiddenClassIdInputEl_dom.value : null; 
            const className = document.getElementById('class_name').value.trim();
            const headTeacher = document.getElementById('head_teacher').value.trim();
            const studentCountStr = document.getElementById('student_count').value;
            const studentCount = studentCountStr.trim() === '' ? null : parseInt(studentCountStr, 10);

            const classData = {
                className: className,
                headTeacher: headTeacher,
                studentCount: studentCount 
            };

            const method = classId ? 'PUT' : 'POST';
            const endpoint = classId ? `/classes/${classId}` : '/classes';

            const originalButtonHTML = saveClassBtn_el_dom.innerHTML; 
            setButtonLoading(saveClassBtn_el_dom, true, '保存中...');

            try {
                await fetchApi(endpoint, method, classData); // 使用 fetchApi
                
                showAdminToast(classId ? '班级信息更新成功！' : '新班级添加成功！', 'success');
                $('#classModal').modal('hide');
                loadClasses_backend(); 

            } catch (error) {
                console.error('Error saving class specifically in saveClassBtn handler:', error);
                // fetchApi 会处理 401/403 及通用错误提示
                // 如果保存操作有特定错误需要UI反馈，可以在这里补充（但 fetchApi 的提示可能已足够）
                // 例如，处理来自 fetchApi 的 error.data 中的字段验证错误
                if (error.status === 400 && error.data && error.data.errors && Array.isArray(error.data.errors)) {
                     let messages = error.data.message || "保存操作失败";
                     messages += "\n" + error.data.errors.map(e => `字段 '${e.field}': ${e.defaultMessage}`).join("\n");
                     showAdminToast(messages, 'error', '保存错误 (校验)');
                } else if (!(error.message && error.message.startsWith('Authentication failed'))) {
                    // 如果不是认证错误（已由 fetchApi 处理），可以显示或记录其他错误
                    // showAdminToast(`保存班级操作失败: ${error.message}`, 'error'); // fetchApi 已显示
                }
            } finally {
                 setButtonLoading(saveClassBtn_el_dom, false, '', originalButtonHTML);
            }
        });
    }
    // ===================================================================================
    // END 班级管理事件绑定
    // ===================================================================================

    // (所有其他模块的mock数据填充和事件绑定逻辑保持不变，并放在这里)
    // ... (您的考试管理、学生管理、成绩管理的现有mock代码)
    // 确保所有 mock 数据的 renderTable, populateDropdowns 等函数调用在其对应的标签页激活逻辑中
    // 例如，考试管理的 renderExamTable() 应该在 exam-management-content 标签页被点击时调用

    // 示例: 旧的考试管理逻辑 (保持不变)
    // ---------- 考试管理模块代码开始 ----------
    const examTableBody = document.getElementById('examTableBody');
    const examModal = $('#examModal');
    const examForm = document.getElementById('examForm');
    const examModalLabel = document.getElementById('examModalLabel');
    const addExamBtn = document.getElementById('addExamBtn');
    const saveExamBtn = document.getElementById('saveExamBtn');
    const hiddenExamIdInput = document.getElementById('exam_id');

    function resetExamForm() {
        if (examForm) {
            examForm.reset();
            if (hiddenExamIdInput) hiddenExamIdInput.value = '';
            examForm.classList.remove('was-validated');
            $(examForm).find('.is-invalid').removeClass('is-invalid');
            $(examForm).find('.is-valid').removeClass('is-valid');
        }
        if (examModalLabel) examModalLabel.textContent = '新增考试';
    }

    function validateExamForm() {
        if (!examForm) return false;
        let isValid = true;
        
        $(examForm).find('.is-invalid').removeClass('is-invalid'); // 清除旧的验证状态

        // 示例校验：考试名称、科目、考试时间、地点不能为空
        const examName = document.getElementById('exam_name').value.trim();
        const subject = document.getElementById('subject').value.trim();
        const examTime = document.getElementById('exam_time').value;
        const location = document.getElementById('location').value.trim();

        if (!examName) {
            $('#exam_name').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#exam_name').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!subject) {
            $('#subject').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#subject').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!examTime) {
            $('#exam_time').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#exam_time').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!location) {
            $('#location').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#location').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }

        // 使用HTML5内置验证
        if (!examForm.checkValidity()) {
            examForm.classList.add('was-validated');
            isValid = false;
        }
        return isValid;
    }

    async function loadExams_backend() {
        if (!examTableBody) {
            console.error("Exam table body not found!");
            return;
        }
        showTableLoadingSpinner(examTableBody, 9);
        try {
            const exams = await fetchApi('/exams');
            renderExamTable_backend(exams);
        } catch (error) {
            console.error('Error loading exams:', error);
            if (!(error.message && error.message.startsWith('Authentication failed'))) {
                examTableBody.innerHTML = `<tr><td colspan="9" class="text-center text-danger">加载考试数据时发生错误: ${error.message}</td></tr>`;
            }
        }
    }

    function renderExamTable_backend(exams) {
        if (!examTableBody) return;
        examTableBody.innerHTML = ''; 

        if (!exams || exams.length === 0) {
            examTableBody.innerHTML = '<tr><td colspan="9" class="text-center">暂无考试数据</td></tr>';
            return;
        }

        exams.forEach(exam => {
            const row = examTableBody.insertRow();
            row.innerHTML = `
                <td>${exam.id}</td>
                <td>${exam.examName || 'N/A'}</td>
                <td>${exam.subject || 'N/A'}</td>
                <td>${exam.examTime ? formatDateTime(exam.examTime) : 'N/A'}</td>
                <td>${exam.location || 'N/A'}</td>
                <td>${exam.description || 'N/A'}</td>
                <td>${exam.createTime ? formatDateTime(exam.createTime) : 'N/A'}</td>
                <td>${exam.updateTime ? formatDateTime(exam.updateTime) : 'N/A'}</td>
                <td class="action-buttons">
                    <button class="btn btn-sm btn-info edit-exam-btn" data-id="${exam.id}" title="编辑"><i class="fas fa-edit"></i> 编辑</button>
                    <button class="btn btn-sm btn-danger delete-exam-btn" data-id="${exam.id}" data-name="${exam.examName || '该考试'}" title="删除"><i class="fas fa-trash"></i> 删除</button>
                </td>
            `;
            row.querySelector('.edit-exam-btn').addEventListener('click', () => handleEditExamShowModal_backend(exam));
            const deleteBtn = row.querySelector('.delete-exam-btn');
            deleteBtn.addEventListener('click', (event) => handleDeleteExam_backend(exam.id, exam.examName || 'ID: '+exam.id, event.currentTarget));
        });
    }

    function handleEditExamShowModal_backend(examObj) { 
        resetExamForm();
        
        hiddenExamIdInput.value = examObj.id;
        document.getElementById('exam_name').value = examObj.examName || '';
        document.getElementById('subject').value = examObj.subject || '';
        // 后端返回的 examTime 可能是 LocalDateTime 对象，需要格式化为 datetime-local input 所需的格式
        // LocalDateTime.toString() 通常是 "YYYY-MM-DDTHH:mm:ss.sss" 格式，可以被 datetime-local input 直接使用
        // 如果有秒的小数部分，可能需要截断。简单起见，我们假设它可以直接用，或后端DTO已处理。
        document.getElementById('exam_time').value = examObj.examTime ? examObj.examTime.toString().substring(0, 16) : ''; // YYYY-MM-DDTHH:mm
        document.getElementById('location').value = examObj.location || '';
        document.getElementById('description').value = examObj.description || '';
        
        examModalLabel.textContent = '编辑考试';
        examModal.modal('show');
    }

    async function handleDeleteExam_backend(examId, examName, deleteButton) {
        if (!confirm(`确定要删除考试 "${examName}" 吗？此操作不可恢复。`)) {
            return;
        }
        
        const originalButtonHTML = deleteButton ? deleteButton.innerHTML : null;
        if(deleteButton) setButtonLoading(deleteButton, true, '', originalButtonHTML);

        try {
            await fetchApi(`/exams/${examId}`, 'DELETE');
            showAdminToast(`考试 "${examName}" 删除成功！`, 'success');
            loadExams_backend();
        } catch (error) {
            console.error('Failed to delete exam:', error);
            // fetchApi 会处理通用错误和认证错误
        } finally {
            if(deleteButton) setButtonLoading(deleteButton, false, '', originalButtonHTML);
        }
    }

    if (addExamBtn) {
        addExamBtn.addEventListener('click', function() {
            resetExamForm();
        });
    }

    if (saveExamBtn) {
        saveExamBtn.addEventListener('click', async function() {
            if (!validateExamForm()) {
                showAdminToast('请检查表单，确保所有必填项都已正确填写。', 'warning', '表单无效');
                return;
            }
            const examId = hiddenExamIdInput.value;
            const examData = {
                examName: document.getElementById('exam_name').value.trim(),
                subject: document.getElementById('subject').value.trim(),
                examTime: document.getElementById('exam_time').value, 
                location: document.getElementById('location').value.trim(),
                description: document.getElementById('description').value.trim()
            };
            const method = examId ? 'PUT' : 'POST';
            const endpoint = examId ? `/exams/${examId}` : '/exams';
            const originalButtonHTML = saveExamBtn.innerHTML;
            setButtonLoading(saveExamBtn, true, '保存中...');
            try {
                await fetchApi(endpoint, method, examData);
                showAdminToast(examId ? '考试信息更新成功！' : '新考试添加成功！', 'success');
                examModal.modal('hide');
                loadExams_backend();
            } catch (error) {
                console.error('Error saving exam:', error);
                // fetchApi 会处理通用错误和认证错误
                // 如果需要针对特定状态码（如400校验错误）做额外处理，可以在这里添加
                if (error.status === 400 && error.data && error.data.message) {
                     showAdminToast(`保存失败: ${error.data.message}`, 'error', '校验错误');
                }
            } finally {
                setButtonLoading(saveExamBtn, false, '', originalButtonHTML);
            }
        });
    }
    // ---------- 考试管理模块代码结束 ----------


    // (Similarly for Student and Grade management using MOCK data)
    // Make sure populateClassDropdown, populateStudentDropdown, populateExamDropdown used by
    // student and grade mock logic are defined or moved to global helpers if needed by backend versions later.


}); // End of DOMContentLoaded 

// ===================================================================================
// 成绩管理模块 (Grade Management) - 后端对接
// ===================================================================================
const gradeTableBody = document.getElementById('gradeTableBody'); // 假设HTML中有 <tbody id="gradeTableBody"></tbody>
const gradeModal = $('#gradeModal'); // 假设HTML中有 <div class="modal" id="gradeModal">...</div>
const gradeForm = document.getElementById('gradeForm'); // 假设HTML中有 <form id="gradeForm">...</form>
const gradeModalLabel = document.getElementById('gradeModalLabel'); // 假设模态框标题ID
const addGradeBtn = document.getElementById('addGradeBtn'); // 假设HTML中有 <button id="addGradeBtn">新增成绩</button>
const saveGradeBtn = document.getElementById('saveGradeBtn'); // 假设模态框中的保存按钮ID
const hiddenGradeIdInput = document.getElementById('grade_id'); // 隐藏域存储成绩ID: <input type="hidden" id="grade_id">

// 表单字段 (假设的ID，请根据您的HTML调整)
// const gradeStudentIdInput = document.getElementById('grade_student_id'); // Now select
// const gradeExamIdInput = document.getElementById('grade_exam_id'); // Now select
// const gradeScoreInput = document.getElementById('grade_score'); // Still input


function resetGradeForm() {
    const currentGradeForm = document.getElementById('gradeForm'); // Get form inside function
    if (currentGradeForm) {
        currentGradeForm.reset();
        const hiddenGradeIdElem = document.getElementById('grade_id');
        if (hiddenGradeIdElem) {
            hiddenGradeIdElem.value = '';
            if (hiddenGradeIdElem.dataset.studentId) {
                delete hiddenGradeIdElem.dataset.studentId; // Clean up stored studentId
            }
        }
        currentGradeForm.classList.remove('was-validated');
        $(currentGradeForm).find('.is-invalid').removeClass('is-invalid');
        $(currentGradeForm).find('.is-valid').removeClass('is-valid');
        
        const studentIdInput = document.getElementById('grade_student_id'); // Now an input
        if (studentIdInput) {
            studentIdInput.disabled = false;
            studentIdInput.required = true; 
        }
        // No need to manage studentNameDisplay or studentFeedback specifically for display modes anymore

        const examSelect = document.getElementById('grade_exam_id');
        if (examSelect) examSelect.disabled = false;
    }

    const currentGradeModalLabel = document.getElementById('gradeModalLabel');
    if (currentGradeModalLabel) currentGradeModalLabel.textContent = '新增成绩'; 
    
    const currentSaveGradeBtn = document.getElementById('saveGradeBtn');
    if (currentSaveGradeBtn) {
        if(currentSaveGradeBtn.dataset.originalHTML) {
            setButtonLoading(currentSaveGradeBtn, false, '', currentSaveGradeBtn.dataset.originalHTML);
            delete currentSaveGradeBtn.dataset.originalHTML; // Clean up
        } else {
            currentSaveGradeBtn.disabled = false;
            currentSaveGradeBtn.innerHTML = '保存成绩';
        }
    }
}

async function loadGrades_backend() {
    if (!gradeTableBody) {
        console.error("Grade table body (#gradeTableBody) not found for loading grades!");
        return;
    }
    showTableLoadingSpinner(gradeTableBody, 8); // 8列

    try {
        const responseData = await fetchApi('/grades/admin', 'GET');
        let gradesArray = null;
        let apiMessage = null;
        let operationConsideredSuccess = false;

        if (Array.isArray(responseData)) {
            // 情况1: API直接返回成绩数组
            gradesArray = responseData;
            operationConsideredSuccess = true; 
        } else if (responseData && typeof responseData === 'object' && responseData !== null) {
            // 情况2: API返回一个包装对象
            if (Array.isArray(responseData.data)) {
                gradesArray = responseData.data;
                // 即使有 data 数组，也检查外层是否有成功/失败的明确标记
                if (responseData.success === true || (responseData.status && (responseData.status === 200 || String(responseData.status).toLowerCase() === 'success'))) {
                    operationConsideredSuccess = true;
                } else if (responseData.success === false) {
                    operationConsideredSuccess = false;
                    apiMessage = responseData.message || '操作失败 (来自包装对象)';
                } else {
                    // 没有明确的 success/failure 标记，但有 data 数组，我们暂时认为数据是有效的
                    operationConsideredSuccess = true; 
                }
            } else if (responseData.message) {
                // 返回的是一个对象，但没有 .data 数组，反而有 .message，可能是一个错误对象
                operationConsideredSuccess = false;
                apiMessage = responseData.message;
            } else {
                // 是一个对象，但结构未知，且不包含可识别的成绩数组
                operationConsideredSuccess = false;
                apiMessage = '响应格式未知或数据字段缺失';
            }
        } else if (responseData === null && config.method !== 'DELETE') {
            // fetchApi 对于 204 No Content (通常用于DELETE成功) 会返回 null。
            // 如果不是DELETE请求，但收到null，也视为一种意外情况。
            operationConsideredSuccess = false;
            apiMessage = '服务器未返回任何内容 (null)';
        } else {
            // 其他意外情况，例如 responseData 是字符串或数字等非预期类型
            operationConsideredSuccess = false;
            apiMessage = '收到的响应类型不正确';
        }

        if (operationConsideredSuccess && gradesArray !== null) {
            renderGradeTable_backend(gradesArray);
        } else {
            const errorMsgToShow = apiMessage || '未知错误或数据无法解析';
            showAdminToast(`加载成绩数据失败: ${errorMsgToShow}`, 'error');
            gradeTableBody.innerHTML = `<tr><td colspan="8" class="text-center text-danger">加载失败: ${errorMsgToShow}</td></tr>`;
            console.error('Failed to load or parse grades:', apiMessage, 'Raw ResponseData:', responseData);
        }

    } catch (error) {
        console.error('Exception in loadGrades_backend (after fetchApi call):', error);
        // fetchApi 内部的错误（如网络错误、401/403）应该已经显示了Toast
        // 这个catch主要是处理表格的最终显示状态，以防万一Toast未覆盖或有其他JS错误
        if (gradeTableBody.querySelector('.spinner-border')) { // 如果还在加载状态
            gradeTableBody.innerHTML = `<tr><td colspan="8" class="text-center text-danger">加载成绩数据时发生异常，请检查控制台。</td></tr>`;
        }
    } finally {
        // 确保 spinner 被移除，但避免覆盖上面明确设置的错误信息
        const spinnerCell = gradeTableBody.querySelector('td[colspan="8"] .spinner-border');
        if (spinnerCell) {
            // 如果表格内容还是初始的 spinner，则清空它，renderGradeTable_backend 会处理空数组情况
            // 如果已经变成了错误信息，则不动它
            const parentTd = spinnerCell.closest('td');
            if (parentTd && parentTd.textContent.includes('正在加载数据')) { // 检查是否还是加载文本
                 gradeTableBody.innerHTML = ''; // 清空加载动画，renderGradeTable_backend会处理后续显示
            }
        }
    }
}

function renderGradeTable_backend(grades) {
    const gradeTableBody = document.getElementById('gradeTableBody'); // 确保 gradeTableBody 在此作用域或全局作用域有效
    if (!gradeTableBody) {
        console.error("gradeTableBody not found in renderGradeTable_backend");
        return;
    }
    gradeTableBody.innerHTML = ''; 

    if (!grades || grades.length === 0) {
        gradeTableBody.innerHTML = '<tr><td colspan="8" class="text-center">暂无成绩数据</td></tr>';
        return;
    }

    grades.forEach(grade => {
        const row = gradeTableBody.insertRow();
        row.innerHTML = `
            <td>${grade.id}</td>
            <td>${grade.studentStuNo || 'N/A'}</td>
            <td>${grade.studentName || 'N/A'}</td>
            <td>${grade.examName || 'N/A'}</td>
            <td>${grade.examSubject || 'N/A'}</td>
            <td>${grade.score}</td>
            <td>${formatDateTime(grade.updateTime)}</td>
            <td>
                <button class="btn btn-sm btn-info mr-1 edit-grade-btn" data-id="${grade.id}">编辑</button>
                <button class="btn btn-sm btn-danger delete-grade-btn" data-id="${grade.id}">删除</button>
            </td>
        `;
    });
}

async function handleEditGradeShowModal_backend(gradeId) {
    resetGradeForm(); // Calls the modified resetGradeForm

    const modalLabel = document.getElementById('gradeModalLabel');
    const hiddenIdInput = document.getElementById('grade_id');
    const studentIdInputElem = document.getElementById('grade_student_id'); // Now an input
    const examSelectElem = document.getElementById('grade_exam_id');
    const scoreInputElem = document.getElementById('grade_score');
    const saveBtn = document.getElementById('saveGradeBtn');

    // Removed studentNameDisplayElem and studentFeedbackElem from here as they are no longer used for this layout
    if (!modalLabel || !hiddenIdInput || !studentIdInputElem || !examSelectElem || !scoreInputElem || !saveBtn) {
        showAdminToast('编辑成绩所需的表单元素未全部找到，请检查HTML。', 'error');
        return;
    }

    modalLabel.textContent = '编辑成绩';
    
    studentIdInputElem.disabled = true; // Disable student ID input for editing
    studentIdInputElem.required = false; // Not required when disabled
 
    examSelectElem.disabled = false;   

    setButtonLoading(saveBtn, true, '加载中...'); 

    try {
        // Dropdown population for student and exam should have happened when the tab was opened.
        // No need to call populate...ForForm here again unless they might be empty.

        const gradeToEdit = await fetchApi(`/grades/admin/${gradeId}`, 'GET');

        if (gradeToEdit && gradeToEdit.id !== undefined) { // Assuming fetchApi returns the grade DTO directly or unwrapped
            hiddenIdInput.value = gradeToEdit.id;
            // No need to store studentId in dataset anymore as we will get it from gradeToEdit directly for display
            // and it won't be submitted from the disabled input field for edit.
            // The studentId for PUT request will be taken from gradeToEdit.studentId or a similar source
            // if not directly from the (disabled) form field.
            // For now, `handleSaveGrade_backend` will rely on the disabled field having the correct value set here.

            studentIdInputElem.value = gradeToEdit.studentId; // Display student ID
            examSelectElem.value = gradeToEdit.examId;
            scoreInputElem.value = gradeToEdit.score;
            
            // No need for studentNameDisplayElem logic here

            if (examSelectElem.value !== String(gradeToEdit.examId)) {
                console.warn(`Exam ID ${gradeToEdit.examId} not found in select options, or select not populated.`);
            }

            $('#gradeModal').modal('show');
        } else {
            showAdminToast(`获取成绩详情失败: ${gradeToEdit ? gradeToEdit.message : '未知错误或未找到成绩'}`, 'error');
        }
    } catch (error) {
        console.error('Error fetching grade details for edit:', error);
        showAdminToast(`获取成绩详情出错 (JS): ${error.message}`, 'error');
    } finally {
        setButtonLoading(saveBtn, false, '保存更改'); 
    }
}

async function handleSaveGrade_backend(event) {
    console.log("[DEBUG] handleSaveGrade_backend called. Event:", event); 
    if (!event) {
        console.error("[DEBUG] Event object is missing in handleSaveGrade_backend!"); 
        return false; 
    }
    try {
    event.preventDefault();
        console.log("[DEBUG] event.preventDefault() called."); 
    } catch (e) {
        console.error("[DEBUG] Error calling event.preventDefault():", e); 
        return; 
    }

    const currentForm = event.target; // Get form from event
    const submitButton = event.submitter; // Get submit button from event

    if (!currentForm.checkValidity()) {
        event.stopPropagation();
        currentForm.classList.add('was-validated');
        showAdminToast('请检查表单输入项!', 'warning');
        return;
    }
    
    if (!submitButton) { 
        console.error("[DEBUG] Submit button not found in event.submitter for handleSaveGrade_backend");
        showAdminToast('无法找到提交按钮，操作中止。', 'error');
        return;
    }
    const originalButtonHtml = submitButton.innerHTML;
    // submitButton.dataset.originalHTML = originalButtonHtml; // setButtonLoading handles storing originalHTML if needed
    setButtonLoading(submitButton, true, '保存中...');

    // Get form elements reliably inside the function
    const hiddenGradeIdElem = document.getElementById('grade_id');
    const studentIdInputForSubmit = currentForm.elements.studentId; // This is <input name="studentId"> 
    const examSelectForSubmit = currentForm.elements.examId;       // This is <select name="examId">
    const scoreInputForSubmit = currentForm.elements.score;         // This is <input name="score">

    const gradeId = hiddenGradeIdElem ? hiddenGradeIdElem.value : null;
    let studentIdToSubmit;

    if (gradeId) { // EDIT operation
        // For edit, studentId comes from the disabled input field, which was set in handleEditGradeShowModal_backend
        // Or, more robustly, if we had stored it somewhere else (like a data attribute on a non-form element or a global var for the modal)
        // For now, relying on the disabled input having the correct value.
        studentIdToSubmit = studentIdInputForSubmit ? studentIdInputForSubmit.value : null;
        if (!studentIdToSubmit) {
            console.error("[DEBUG] Student ID missing from disabled input during edit. Value was:", studentIdInputForSubmit ? studentIdInputForSubmit.value : 'undefined');
            showAdminToast('编辑操作缺少学生ID，无法保存。', 'error');
            setButtonLoading(submitButton, false, '', originalButtonHtml);
        return;
        }
    } else { // ADD operation
        studentIdToSubmit = studentIdInputForSubmit ? studentIdInputForSubmit.value : null;
    }

    const examId = examSelectForSubmit ? examSelectForSubmit.value : null;
    const scoreString = scoreInputForSubmit ? scoreInputForSubmit.value : null;


    if ((studentIdToSubmit === null || String(studentIdToSubmit).trim() === '') || // Student ID is always required now
        examId === null || String(examId).trim() === '' || 
        scoreString === null || String(scoreString).trim() === '') {
        showAdminToast('学生ID、考试和分数都不能为空!', 'error'); // Updated message
        setButtonLoading(submitButton, false, '', originalButtonHtml);
        return;
    }

    const parsedStudentId = parseInt(studentIdToSubmit, 10);
    const parsedExamId = parseInt(examId, 10);
    const parsedScore = parseInt(scoreString, 10);

    if (isNaN(parsedStudentId) || 
        isNaN(parsedExamId) || 
        isNaN(parsedScore) || parsedScore < 0) {
        showAdminToast('学生ID, 考试ID必须是有效数字，分数必须是非负数字!', 'error');
        setButtonLoading(submitButton, false, '', originalButtonHtml);
        return;
    }

    const gradeData = {
        studentId: parsedStudentId,
        examId: parsedExamId,
        score: parsedScore
    };

    const method = gradeId ? 'PUT' : 'POST';
    const endpoint = gradeId ? `/grades/admin/${gradeId}` : '/grades/admin';

    try {
        const result = await fetchApi(endpoint, method, gradeData); 

        let operationSuccess = false;
        let successMessage = gradeId ? '成绩更新成功!' : '成绩新增成功!';

        if (result && result.id && result.studentId !== undefined) { 
                operationSuccess = true;
        } else if (method === 'PUT' && result === null) { 
            // Assuming our backend for PUT returns the updated DTO, not 204. 
            // If it could return 204 for success, this condition would need adjustment.
        } else if (result && result.success === true ) { 
                operationSuccess = true;
            if(result.message) successMessage = result.message;
        }

        if (operationSuccess) {
            showAdminToast(successMessage, 'success');
            $('#gradeModal').modal('hide'); // Using direct jQuery selector for modal
            loadGrades_backend(); 
        } else {
            const backendErrorMessage = result && result.error ? result.error : (result && result.message ? result.message : '保存成绩操作未收到明确成功信号，请检查响应。');
            showAdminToast(backendErrorMessage, 'warning'); 
            console.warn("Save grade operation status unclear, response:", result);
        }
    } catch (error) {
        console.error('Error saving grade (in catch block):', error);
        let displayErrorMessage = `保存成绩失败: ${error.message}`;
        if (error.data && error.data.error) { 
            displayErrorMessage = error.data.error;
        } else if (error.responseJSON && error.responseJSON.error) { 
            displayErrorMessage = error.responseJSON.error;
        } else if (typeof error.message === 'string' && error.message.includes("Failed to fetch")) {
            displayErrorMessage = "网络错误，无法连接到服务器。请检查网络连接和后端服务是否运行。";
        }
        if(error.status) {
            displayErrorMessage += ` (状态码: ${error.status})`;
        }
        showAdminToast(displayErrorMessage, 'error');
    } finally {
        setButtonLoading(submitButton, false, '', originalButtonHtml);
    }
}

async function handleDeleteGrade_backend(gradeId, deleteButton) {
    if (!confirm('确定要删除这条成绩记录吗？此操作不可恢复。')) return; // Added more descriptive confirm message

    let originalButtonHTML = '';
    if(deleteButton) {
        originalButtonHTML = deleteButton.innerHTML;
        // dataset.originalHTML is now handled by setButtonLoading if originalContent is passed as null
        setButtonLoading(deleteButton, true, '删除中...');
    }

    try {
        // fetchApi for a successful DELETE (204 No Content) will return null.
        await fetchApi(`/grades/admin/${gradeId}`, 'DELETE');
        // If fetchApi does not throw an error, the DELETE was successful (e.g., 204).
            showAdminToast('成绩删除成功!', 'success');
        loadGrades_backend(); // Reload the list
    } catch (error) {
        console.error('Error deleting grade:', error);
        // fetchApi should have already shown a toast for network errors or 401/403.
        // We might want to show a specific message if the status is 404 (Not Found).
        if (error.status === 404) {
            showAdminToast(`删除失败: 未找到ID为 ${gradeId} 的成绩记录。`, 'error');
        } else if (error.message && !error.message.toLowerCase().includes('failed to fetch') && 
                   !error.message.toLowerCase().includes('authentication failed') && 
                   !error.message.toLowerCase().includes('authorization failed')) {
            // Show a generic error if it's not a handled one by fetchApi or a specific 404
            showAdminToast(`删除操作出错: ${error.message}`, 'error');
        }
        // If fetchApi handled the error toast (e.g. network, auth), no need to show another one here.
    } finally {
        if(deleteButton) {
            // Pass originalButtonHTML to restore, or null if setButtonLoading should use its stored one
            setButtonLoading(deleteButton, false, '', originalButtonHTML);
        }
    }
}

// 初始化和事件监听 (确保在DOM加载完成后执行)
document.addEventListener('DOMContentLoaded', () => {
    console.log("[DEBUG] DOMContentLoaded for grades (second one) fired."); // DEBUG ADDED

    // ... (保留班级管理和考试管理的事件监听器) ...

    // 成绩管理事件监听
    const addGradeBtn_local = document.getElementById('addGradeBtn'); // Using local var for clarity
    const gradeForm_local_submit = document.getElementById('gradeForm'); 
    const gradeTableBody_local = document.getElementById('gradeTableBody');
    const gradeFilterForm_local = document.getElementById('gradeFilterForm');
    const applyGradeFilterBtn_local = document.getElementById('applyGradeFilterBtn');
    const resetGradeFilterBtn_local = document.getElementById('resetGradeFilterBtn');
    const calculateStatsBtn_local = document.getElementById('calculateStatsBtn');


    if (addGradeBtn_local) { // Changed from global addGradeBtn to local
        addGradeBtn_local.addEventListener('click', () => {
            resetGradeForm();
            if (gradeModalLabel) gradeModalLabel.textContent = '新增成绩'; // gradeModalLabel is global
            gradeModal.modal('show'); // gradeModal is global jQuery object
        });
    }

    if (gradeForm_local_submit) {
        console.log("[DEBUG] Attaching submit listener to gradeForm:", gradeForm_local_submit); // DEBUG ADDED
        gradeForm_local_submit.addEventListener('submit', handleSaveGrade_backend);
    } else {
        console.error("[DEBUG] Could not find gradeForm (id='gradeForm') to attach listener!"); // DEBUG ADDED
    }

    if (gradeTableBody_local) { // Changed from global gradeTableBody
        gradeTableBody_local.addEventListener('click', (event) => {
            if (event.target.classList.contains('edit-grade-btn')) {
                const gradeId = event.target.dataset.id;
                handleEditGradeShowModal_backend(gradeId);
            }
            if (event.target.classList.contains('delete-grade-btn')) {
                const gradeId = event.target.dataset.id;
                handleDeleteGrade_backend(gradeId, event.target);
            }
        });
    }

    // 页面加载时，如果grade-management-content存在并且gradeTableBody_local也存在 (基于修改后的逻辑)
    // 这段逻辑可能需要调整，因为初始加载是在导航点击时处理的
    // if (document.getElementById('grade-management-content') && gradeTableBody_local) { 
    // }

    // ---------- 成绩管理筛选和重置按钮事件监听 ----------
    // Using locally scoped variables for buttons if their primary interaction is within this DOMContentLoaded
    
    if (applyGradeFilterBtn_local && gradeForm_local_submit) { // applyGradeFilterBtn also changed to local
        applyGradeFilterBtn_local.addEventListener('click', async () => {
            const filterExamIdEl = document.getElementById('filterExamId');
            const filterClassIdGradesEl = document.getElementById('filterClassIdGrades');
            const filterStudentNameGradesEl = document.getElementById('filterStudentNameGrades');

            const examId = filterExamIdEl ? filterExamIdEl.value : '';
            const classId = filterClassIdGradesEl ? filterClassIdGradesEl.value : '';
            const studentName = filterStudentNameGradesEl ? filterStudentNameGradesEl.value.trim() : '';

            let queryParams = [];
            if (examId) queryParams.push(`examId=${encodeURIComponent(examId)}`);
            if (classId) queryParams.push(`classId=${encodeURIComponent(classId)}`);
            if (studentName) queryParams.push(`studentName=${encodeURIComponent(studentName)}`);
            
            const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
            
            showTableLoadingSpinner(gradeTableBody_local, 8);
            try {
                const responseData = await fetchApi(`/grades/admin/search${queryString}`, 'GET');
                let gradesArray = null;
                let apiMessage = null;
                let operationConsideredSuccess = false;

                if (Array.isArray(responseData)) {
                    gradesArray = responseData;
                    operationConsideredSuccess = true; 
                } else if (responseData && typeof responseData === 'object' && responseData !== null) {
                    if (Array.isArray(responseData.data)) {
                        gradesArray = responseData.data;
                        operationConsideredSuccess = responseData.success === true || (responseData.status && responseData.status === 200);
                        if(!operationConsideredSuccess && responseData.message) apiMessage = responseData.message;
                    } else if (responseData.message && responseData.success === false) {
                        operationConsideredSuccess = false;
                        apiMessage = responseData.message;
                    } else {
                        operationConsideredSuccess = false;
                        apiMessage = '筛选响应格式未知或数据字段缺失';
                    }
                } else {
                    operationConsideredSuccess = false;
                    apiMessage = '筛选响应类型不正确或服务器未返回有效内容';
                }

                if (operationConsideredSuccess && gradesArray !== null) {
                    renderGradeTable_backend(gradesArray);
                } else {
                    const errorMsgToShow = apiMessage || '筛选失败或无结果';
                    showAdminToast(`筛选成绩失败: ${errorMsgToShow}`, 'error');
                    if (gradeTableBody_local) gradeTableBody_local.innerHTML = `<tr><td colspan="8" class="text-center text-danger">筛选失败: ${errorMsgToShow}</td></tr>`;
                }

            } catch (error) {
                console.error('Error applying grade filter:', error);
                showAdminToast(`筛选成绩时发生错误: ${error.message}`, 'error');
                if (gradeTableBody_local) gradeTableBody_local.innerHTML = `<tr><td colspan="8" class="text-center text-danger">筛选错误，请查看控制台。</td></tr>`;
            }
        });
    }

    if (resetGradeFilterBtn_local && gradeForm_local_submit) { // resetGradeFilterBtn also changed to local
        resetGradeFilterBtn_local.addEventListener('click', () => {
            if(gradeForm_local_submit) gradeForm_local_submit.reset(); // Reset the correct form
            
            // Explicitly reset select elements if simple form.reset() doesn't clear them as expected
            const filterExamIdEl = document.getElementById('filterExamId');
            if(filterExamIdEl) filterExamIdEl.value = '';
            const filterClassIdGradesEl = document.getElementById('filterClassIdGrades');
            if(filterClassIdGradesEl) filterClassIdGradesEl.value = '';
            const filterStudentNameGradesEl = document.getElementById('filterStudentNameGrades'); // Get the element
            if(filterStudentNameGradesEl) filterStudentNameGradesEl.value = ''; // Explicitly clear its value

            loadGrades_backend();

            // Clear the grade statistics container
            const gradeStatsContainerEl = document.getElementById('gradeStatsContainer');
            if (gradeStatsContainerEl) {
                gradeStatsContainerEl.innerHTML = '';
                console.log("[DEBUG] Grade stats container cleared on filter reset."); // DEBUG ADDED
            }
        });
    }

    if (calculateStatsBtn_local) { // calculateStatsBtn also changed to local
        console.log('[DEBUG] 成绩统计按钮的事件监听器已设置 (using local var)');
        calculateStatsBtn_local.addEventListener('click', async () => {
            console.log('[DEBUG] 成绩统计按钮被点击 (local var)');
            const studentIdStr = prompt("请输入需要统计成绩的学生ID:", "");
            console.log('获取到的学生ID字符串:', studentIdStr);

            if (!studentIdStr || isNaN(parseInt(studentIdStr.trim()))) {
                if (studentIdStr !== null) { 
                    showAdminToast('请输入有效的学生ID数字。', 'warning');
                    console.warn('输入的学生ID无效:', studentIdStr);
                }
                return;
            }
            const studentId = parseInt(studentIdStr.trim());
            console.log('解析后的学生ID:', studentId);

            const statsLoadingToastId = showAdminToast('正在获取学生成绩统计...', 'info', '统计中');
            console.log('准备调用fetchApi获取统计数据，学生ID:', studentId);

            try {
                const statsDataFromApi = await fetchApi(`/grades/admin/stats?studentId=${studentId}`, 'GET');
                console.log('fetchApi调用完成，获取到的原始stats数据:', JSON.stringify(statsDataFromApi, null, 2));

                if (statsLoadingToastId && $('#' + statsLoadingToastId).length) {
                     $('#' + statsLoadingToastId).toast('hide');
                }

                if (statsDataFromApi && statsDataFromApi.average !== undefined && statsDataFromApi.count !== undefined) { 
                    console.log('stats数据有效，准备渲染HTML');
                    
                    // 使用传入的 studentId，studentName 从后端数据中获取（如果存在），否则显示 N/A
                    const studentNameToDisplay = statsDataFromApi.studentName || 'N/A'; 

                    let statsHtml = `
                        <h4>学生 ${studentNameToDisplay} (ID: ${studentId}) 的成绩统计</h4>
                        <p><strong>参加考试总数:</strong> ${statsDataFromApi.count !== undefined ? statsDataFromApi.count : 'N/A'}</p>
                        <p><strong>平均分数:</strong> ${statsDataFromApi.average !== undefined ? parseFloat(statsDataFromApi.average).toFixed(2) : 'N/A'}</p>
                        <p><strong>最高分数:</strong> ${statsDataFromApi.max !== undefined ? statsDataFromApi.max : 'N/A'}</p>
                        <p><strong>最低分数:</strong> ${statsDataFromApi.min !== undefined ? statsDataFromApi.min : 'N/A'}</p>
                        <p><strong>总分数:</strong> ${statsDataFromApi.sum !== undefined ? statsDataFromApi.sum : 'N/A'}</p>
                    `;

                    // 处理 subjectCount 来显示科目和次数
                    if (statsDataFromApi.subjectCount && Object.keys(statsDataFromApi.subjectCount).length > 0) {
                        statsHtml += '<h5>各科目参加考试次数:</h5><ul class="list-group">';
                        for (const subject in statsDataFromApi.subjectCount) {
                            statsHtml += `<li class="list-group-item">
                                ${subject}: ${statsDataFromApi.subjectCount[subject]} 次
                            </li>`;
                        }
                        statsHtml += '</ul>';
                    } else {
                        statsHtml += '<p>该学生暂无详细的科目统计信息。</p>';
                    }
                    
                    if (gradeStatsContainer) { 
                        gradeStatsContainer.innerHTML = statsHtml;
                        showAdminToast('成绩统计加载完毕!', 'success');
                        console.log('统计HTML已渲染到gradeStatsContainer');
                    } else {
                        console.warn('gradeStatsContainer 未找到，使用alert显示统计信息');
                        // Fallback alert, 尽量保持与HTML结构一致的关键信息
                        alert(`学生 ID: ${studentId} 成绩统计:\n参加考试总数: ${statsDataFromApi.count}\n平均分: ${parseFloat(statsDataFromApi.average).toFixed(2)}\n最高分: ${statsDataFromApi.max}\n最低分: ${statsDataFromApi.min}`);
                    }

                } else {
                    const message = statsDataFromApi && statsDataFromApi.message ? statsDataFromApi.message : '未找到该学生的成绩统计数据或数据格式错误。';
                    showAdminToast(message, 'warning', '统计结果');
                    if (gradeStatsContainer) gradeStatsContainer.innerHTML = `<p class="text-warning">${message}</p>`;
                    console.log('stats数据无效或格式不符，显示消息:', message, '原始数据:', statsDataFromApi);
                }
            } catch (error) {
                 if (statsLoadingToastId && $('#' + statsLoadingToastId).length) {
                     $('#' + statsLoadingToastId).toast('hide');
                }
                console.error('计算成绩统计时捕获到错误:', error);
                showAdminToast(`获取成绩统计失败: ${error.message}`, 'error');
                if (gradeStatsContainer) gradeStatsContainer.innerHTML = `<p class="text-danger">获取统计信息失败: ${error.message}</p>`;
            }
        });
    }

}); 

// 学生管理相关函数
async function loadStudents_backend(page = 1, pageSize = 10) {
    const studentTableBody = document.getElementById('studentTableBody');
    if (!studentTableBody) {
        console.error("Student table body not found!");
        return;
    }
    showTableLoadingSpinner(studentTableBody, 9);

    try {
        const response = await fetchApi(`/students/page?page=${page}&pageSize=${pageSize}`, 'GET');
        if (response && response.data) {
            renderStudentTable_backend(response.data.records);
            renderPagination_backend(response.data);
        } else {
            studentTableBody.innerHTML = '<tr><td colspan="9" class="text-center">暂无学生数据</td></tr>';
        }
    } catch (error) {
        console.error('Error loading students:', error);
        showAdminToast('加载学生列表失败', 'error');
        studentTableBody.innerHTML = '<tr><td colspan="9" class="text-center text-danger">加载学生数据失败</td></tr>';
    }
}

// 添加 renderStudentTable 函数
function renderStudentTable(students) {
    const tbody = document.getElementById('studentTableBody');
    if (!tbody) return;

    if (!students || students.length === 0) {
        tbody.innerHTML = '<tr><td colspan="9" class="text-center">暂无学生数据</td></tr>';
        return;
    }

    tbody.innerHTML = students.map(student => `
        <tr>
            <td>${student.id}</td>
            <td>${student.stuNo || 'N/A'}</td>
            <td>${student.name || 'N/A'}</td>
            <td>${student.gender || 'N/A'}</td>
            <td>${student.classId || 'N/A'}</td>
            <td>${student.phone || 'N/A'}</td>
            <td>${student.createTime ? formatDateTime(student.createTime) : 'N/A'}</td>
            <td>${student.updateTime ? formatDateTime(student.updateTime) : 'N/A'}</td>
            <td>
                <button class="btn btn-sm btn-info edit-student-btn" data-id="${student.id}" title="编辑">
                    <i class="fas fa-edit"></i> 编辑
                </button>
                <button class="btn btn-sm btn-danger delete-student-btn" data-id="${student.id}" title="删除">
                    <i class="fas fa-trash"></i> 删除
                </button>
            </td>
        </tr>
    `).join('');

    // 添加编辑和删除按钮的事件监听
    tbody.querySelectorAll('.edit-student-btn').forEach(btn => {
        btn.addEventListener('click', () => handleEditStudentShowModal_backend(btn.dataset.id));
    });

    tbody.querySelectorAll('.delete-student-btn').forEach(btn => {
        btn.addEventListener('click', () => handleDeleteStudent_backend(btn.dataset.id, btn));
    });
}

function renderStudentTable_backend(students) {
    const tbody = document.getElementById('studentTableBody');
    if (!tbody) return;

    if (!students || students.length === 0) {
        tbody.innerHTML = '<tr><td colspan="9" class="text-center">暂无学生数据</td></tr>';
        return;
    }

    tbody.innerHTML = students.map(student => `
        <tr>
            <td>${student.id}</td>
            <td>${student.stuNo || 'N/A'}</td>
            <td>${student.name || 'N/A'}</td>
            <td>${student.gender || 'N/A'}</td>
            <td>${student.classId || 'N/A'}</td>
            <td>${student.phone || 'N/A'}</td>
            <td>${student.createTime ? formatDateTime(student.createTime) : 'N/A'}</td>
            <td>${student.updateTime ? formatDateTime(student.updateTime) : 'N/A'}</td>
            <td>
                <button class="btn btn-sm btn-info edit-student-btn" data-id="${student.id}" title="编辑">
                    <i class="fas fa-edit"></i> 编辑
                </button>
                <button class="btn btn-sm btn-danger delete-student-btn" data-id="${student.id}" title="删除">
                    <i class="fas fa-trash"></i> 删除
                </button>
            </td>
        </tr>
    `).join('');

    // 添加编辑和删除按钮的事件监听
    tbody.querySelectorAll('.edit-student-btn').forEach(btn => {
        btn.addEventListener('click', () => handleEditStudentShowModal_backend(btn.dataset.id));
    });

    tbody.querySelectorAll('.delete-student-btn').forEach(btn => {
        btn.addEventListener('click', () => handleDeleteStudent_backend(btn.dataset.id, btn));
    });
}

function renderPagination_backend(pageInfo) {
    const paginationContainer = document.getElementById('studentPagination');
    if (!paginationContainer) return;

    const totalPages = pageInfo.pages;
    const currentPage = pageInfo.current;

    let paginationHtml = `
        <nav aria-label="学生列表分页">
            <ul class="pagination justify-content-center">
                <li class="page-item ${currentPage === 1 ? 'disabled' : ''}">
                    <a class="page-link" href="#" data-page="${currentPage - 1}">上一页</a>
                </li>
    `;

    // 显示页码按钮
    for (let i = 1; i <= totalPages; i++) {
        if (i === 1 || i === totalPages || (i >= currentPage - 2 && i <= currentPage + 2)) {
            paginationHtml += `
                <li class="page-item ${i === currentPage ? 'active' : ''}">
                    <a class="page-link" href="#" data-page="${i}">${i}</a>
                </li>
            `;
        } else if (i === currentPage - 3 || i === currentPage + 3) {
            paginationHtml += `
                <li class="page-item disabled">
                    <span class="page-link">...</span>
                </li>
            `;
        }
    }

    paginationHtml += `
                <li class="page-item ${currentPage === totalPages ? 'disabled' : ''}">
                    <a class="page-link" href="#" data-page="${currentPage + 1}">下一页</a>
                </li>
            </ul>
        </nav>
    `;

    paginationContainer.innerHTML = paginationHtml;

    // 添加分页事件监听
    paginationContainer.querySelectorAll('.page-link').forEach(link => {
        link.addEventListener('click', (e) => {
            e.preventDefault();
            const page = parseInt(e.target.dataset.page);
            if (!isNaN(page)) {
                loadStudents_backend(page);
            }
        });
    });
}

// 学生筛选功能
async function handleStudentFilter_backend(event) {
    event.preventDefault();
    const form = event.target;
    const formData = new FormData(form);
    
    const params = new URLSearchParams({
        page: 1,
        pageSize: 10,
        name: formData.get('name') || '',
        stuNo: formData.get('stuNo') || '',
        classId: formData.get('classId') || ''
    });

    try {
        const response = await fetchApi(`/students/page?${params.toString()}`, 'GET');
        if (response && response.data) {
            renderStudentTable_backend(response.data.records);
            renderPagination_backend(response.data);
        }
    } catch (error) {
        console.error('Error filtering students:', error);
        showAdminToast('筛选学生失败', 'error');
    }
}

// 重置学生筛选
function resetStudentFilter_backend() {
    const form = document.getElementById('studentFilterForm');
    if (form) {
        form.reset();
        loadStudents_backend(1);
    }
}

// 在 DOMContentLoaded 事件中添加学生管理相关的事件监听
document.addEventListener('DOMContentLoaded', function() {
    console.log("[DEBUG] Student-specific DOMContentLoaded fired."); // 新增日志

    // 学生管理事件监听
    const studentFilterForm = document.getElementById('studentFilterForm');
    const applyStudentFilterBtn = document.getElementById('applyStudentFilterBtn');
    const resetStudentFilterBtn = document.getElementById('resetStudentFilterBtn');

    if (studentFilterForm) {
        studentFilterForm.addEventListener('submit', handleStudentFilter_backend);
        // console.log("[DEBUG] studentFilterForm submit listener attached to handleStudentFilter_backend."); 
    } else {
        // console.error("[DEBUG] studentFilterForm not found for attaching submit listener.");
    }

    // The click listener for applyStudentFilterBtn is no longer needed
    // as it is now type="submit" and will trigger the form's submit event directly.
    // if (applyStudentFilterBtn && studentFilterForm) { ... } 

    if (resetStudentFilterBtn) {
        resetStudentFilterBtn.addEventListener('click', () => {
            // console.log("[DEBUG] resetStudentFilterBtn clicked.");
            resetStudentFilter_backend();
        });
    }

    const studentForm = document.getElementById('studentForm'); // 这是新增/编辑学生的表单
    if (studentForm) {
        // console.log("[DEBUG] Found studentForm in Student-specific DOMContentLoaded, attaching submit listener.", studentForm);
        studentForm.addEventListener('submit', handleSaveStudent_backend); // 这个绑定是正确的
    } else {
        // console.error("[DEBUG] CRITICAL: studentForm not found in Student-specific DOMContentLoaded!");
    }

    // 添加新增学生按钮事件监听
    const addStudentBtn = document.getElementById('addStudentBtn');
    if (addStudentBtn) {
        addStudentBtn.addEventListener('click', () => {
            const studentFormForAdd = document.getElementById('studentForm'); 
            const studentModalLabel = document.getElementById('studentModalLabel');
            const hiddenStudentIdInput = document.getElementById('student_id_form');
            if (studentFormForAdd && studentModalLabel && hiddenStudentIdInput) {
                studentFormForAdd.reset();
                studentFormForAdd.classList.remove('was-validated');
                $(studentFormForAdd).find('.is-invalid').removeClass('is-invalid');
                $(studentFormForAdd).find('.is-valid').removeClass('is-valid');
                hiddenStudentIdInput.value = '';
                studentModalLabel.textContent = '新增学生';
            } else {
                console.error("[DEBUG] Elements for Add Student modal not fully found when clicking addStudentBtn.");
            }
        });
    }
    
    // 为学生模态框的保存按钮添加直接的点击事件监听器 (用于调试)
    const saveStudentBtn = document.getElementById('saveStudentBtn');
    if (saveStudentBtn) {
        // console.log("[DEBUG] Found saveStudentBtn in Student-specific DOMContentLoaded, attaching click listener for debug.", saveStudentBtn);
        saveStudentBtn.addEventListener('click', function(event) {
            // console.log("[DEBUG] saveStudentBtn raw click detected! Type:", event.type, "Target:", event.target, "CurrentTarget:", event.currentTarget);
        });
    } else {
        // console.error("[DEBUG] CRITICAL: saveStudentBtn not found in Student-specific DOMContentLoaded!");
    }
}); 

// 添加学生编辑和删除相关的函数
async function handleEditStudentShowModal_backend(studentId) {
    console.log(`handleEditStudentShowModal_backend called for studentId: ${studentId}`); // 日志1
    const studentModal = $('#studentModal');
    const studentModalLabel = document.getElementById('studentModalLabel');
    const studentForm = document.getElementById('studentForm');
    const hiddenStudentIdInput = document.getElementById('student_id_form');

    if (!studentModal || !studentModalLabel || !studentForm || !hiddenStudentIdInput) {
        showAdminToast('编辑学生所需的表单元素未找到', 'error');
        console.error('Modal elements not found for editing student.'); // 日志2
        return;
    }

    studentForm.reset();
    studentForm.classList.remove('was-validated');
    $(studentForm).find('.is-invalid').removeClass('is-invalid');
    $(studentForm).find('.is-valid').removeClass('is-valid');
    studentModalLabel.textContent = '编辑学生';

    try {
        console.log(`Fetching student data for ID: ${studentId}`); // 日志3
        const student = await fetchApi(`/students/${studentId}`, 'GET');
        console.log('Fetched student data:', student); // 日志4: 观察获取到的原始数据

        if (!student || student.error) { // 后端R.error()可能会包含一个error字段
            const errorMessage = student && student.error ? student.error : (student && student.msg ? student.msg : '未找到学生信息或加载失败');
            showAdminToast(errorMessage, 'error');
            console.error('Failed to fetch student or student data is invalid:', student); // 日志5
            return;
        }
        
        // 确保我们操作的是学生数据本身，如果后端返回的数据被R对象包装了
        const studentDetails = student.data ? student.data : student; 
        console.log('Student details to populate form:', studentDetails); // 日志6: 观察用于填充的实际学生数据

        if (!studentDetails || typeof studentDetails !== 'object') {
            showAdminToast('获取到的学生数据格式不正确', 'error');
            console.error('Student details are not a valid object:', studentDetails); // 日志7
            return;
        }

        hiddenStudentIdInput.value = studentDetails.id;
        document.getElementById('stu_no').value = studentDetails.stuNo || '';
        document.getElementById('name').value = studentDetails.name || '';
        document.getElementById('gender').value = studentDetails.gender || '';
        // 确保班级下拉框的 id 是 class_id_form, name 是 class_id
        const classSelect = document.getElementById('class_id_form');
        if (classSelect) {
            classSelect.value = studentDetails.classId || '';
            // 如果班级ID不存在于下拉选项中，浏览器可能不会选中任何项，或者选中第一个
            if (classSelect.value !== String(studentDetails.classId) && studentDetails.classId !== null && studentDetails.classId !== '') {
                console.warn(`Class ID ${studentDetails.classId} not found in select options for #class_id_form.`); // 日志8
            }
        } else {
            console.error('Class select dropdown #class_id_form not found.'); // 日志9
        }
        document.getElementById('phone').value = studentDetails.phone || '';
        
        console.log('Form population attempt complete.'); // 日志10
        studentModal.modal('show');
    } catch (error) {
        console.error('Error in handleEditStudentShowModal_backend:', error); // 日志11
        showAdminToast(`获取学生信息失败: ${error.message}`, 'error');
    }
}

async function handleDeleteStudent_backend(studentId, deleteButton) {
    if (!confirm('确定要删除这个学生吗？此操作不可恢复。')) {
        return;
    }

    const originalButtonHTML = deleteButton ? deleteButton.innerHTML : null;
    if (deleteButton) {
        setButtonLoading(deleteButton, true, '删除中...');
    }

    try {
        await fetchApi(`/students/${studentId}`, 'DELETE');
        showAdminToast('学生删除成功！', 'success');
        loadStudents_backend(); // 重新加载学生列表
    } catch (error) {
        console.error('Error deleting student:', error);
        showAdminToast(`删除学生失败: ${error.message}`, 'error');
    } finally {
        if (deleteButton) {
            setButtonLoading(deleteButton, false, '', originalButtonHTML);
        }
    }
}

// 添加保存学生信息的函数
async function handleSaveStudent_backend(event) {
    console.log("handleSaveStudent_backend triggered"); // 新增日志
    event.preventDefault();
    const form = event.target;
    
    console.log("Form validity:", form.checkValidity()); // 新增日志
    if (!form.checkValidity()) {
        event.stopPropagation();
        form.classList.add('was-validated');
        showAdminToast('请检查表单，确保所有必填项都已正确填写。错误信息应已显示在相应字段下方。', 'warning'); // 更详细的提示
        return;
    }

    const submitButton = event.submitter;
    console.log("Submit button:", submitButton); // 新增日志
    const originalButtonHTML = submitButton ? submitButton.innerHTML : null;
    if (submitButton) {
        setButtonLoading(submitButton, true, '保存中...');
    }

    // 通过 name 获取表单字段，确保与后端一致
    const studentId = document.getElementById('student_id_form').value;
    const stuNo = form.elements['stu_no'].value.trim();
    const name = form.elements['name'].value.trim();
    const gender = form.elements['gender'].value;
    const classId = form.elements['class_id'].value; // 直接使用 name=\"class_id\"
    const phone = form.elements['phone'].value.trim();

    const studentData = {
        stuNo: stuNo, // 更正为 stuNo
        name: name,
        gender: gender,
        classId: classId, // 更正为 classId
        phone: phone
    };
    console.log("Student data to send:", studentData); // 新增日志

    try {
        const method = studentId ? 'PUT' : 'POST';
        const endpoint = studentId ? `/students/${studentId}` : '/students';
        
        console.log(`Sending ${method} request to ${endpoint}`); // 新增日志
        await fetchApi(endpoint, method, studentData);
        showAdminToast(studentId ? '学生信息更新成功！' : '新学生添加成功！', 'success');
        $('#studentModal').modal('hide');
        loadStudents_backend();
    } catch (error) {
        console.error('Error saving student:', error);
        showAdminToast(`保存学生信息失败: ${error.message}`, 'error');
    } finally {
        if (submitButton) {
            setButtonLoading(submitButton, false, '', originalButtonHTML);
        }
    }
}

// 在 DOMContentLoaded 事件中添加学生表单提交事件监听
document.addEventListener('DOMContentLoaded', function() {
    // ... existing code ...

    // 添加学生表单提交事件监听
    const studentForm = document.getElementById('studentForm');
    if (studentForm) {
        studentForm.addEventListener('submit', handleSaveStudent_backend);
    }

    // 添加新增学生按钮事件监听
    const addStudentBtn = document.getElementById('addStudentBtn');
    if (addStudentBtn) {
        addStudentBtn.addEventListener('click', () => {
            const studentForm = document.getElementById('studentForm');
            const studentModalLabel = document.getElementById('studentModalLabel');
            const hiddenStudentIdInput = document.getElementById('student_id_form');

            if (studentForm && studentModalLabel && hiddenStudentIdInput) {
                studentForm.reset();
                studentForm.classList.remove('was-validated');
                $(studentForm).find('.is-invalid').removeClass('is-invalid');
                $(studentForm).find('.is-valid').removeClass('is-valid');
                hiddenStudentIdInput.value = '';
                studentModalLabel.textContent = '新增学生';
            }
        });
    }
}); 

// 新增：加载仪表盘统计数据
async function loadDashboardStats() {
    const totalStudentsElem = document.getElementById('totalStudentsStat');
    const totalClassesElem = document.getElementById('totalClassesStat');
    const totalExamsElem = document.getElementById('totalExamsStat');

    // 设置为加载中状态，以防之前有错误信息
    if(totalStudentsElem) totalStudentsElem.textContent = '加载中...';
    if(totalClassesElem) totalClassesElem.textContent = '加载中...';
    if(totalExamsElem) totalExamsElem.textContent = '加载中...';

    try {
        const response = await fetchApi('/dashboard/stats', 'GET');
        if (response && response.data) {
            const stats = response.data;
            if(totalStudentsElem) totalStudentsElem.textContent = stats.totalStudents !== undefined ? stats.totalStudents : 'N/A';
            if(totalClassesElem) totalClassesElem.textContent = stats.totalClasses !== undefined ? stats.totalClasses : 'N/A';
            if(totalExamsElem) totalExamsElem.textContent = stats.totalExams !== undefined ? stats.totalExams : 'N/A';
        } else {
            if(totalStudentsElem) totalStudentsElem.textContent = '获取失败';
            if(totalClassesElem) totalClassesElem.textContent = '获取失败';
            if(totalExamsElem) totalExamsElem.textContent = '获取失败';
            console.error('Failed to load dashboard stats or data is missing:', response);
            showAdminToast('加载仪表盘统计数据失败。', 'error');
        }
    } catch (error) {
        if(totalStudentsElem) totalStudentsElem.textContent = '错误';
        if(totalClassesElem) totalClassesElem.textContent = '错误';
        if(totalExamsElem) totalExamsElem.textContent = '错误';
        console.error('Error fetching dashboard stats:', error);
        showAdminToast(`加载仪表盘统计数据时出错: ${error.message}`, 'error');
    }
}

// ===================================================================================
// DOMContentLoaded - 页面加载完成后的主要初始化逻辑
// ===================================================================================
document.addEventListener('DOMContentLoaded', function() {
    const adminNameSpan = document.getElementById('adminName');
    const currentUser = getCurrentUser(); // 假设 auth.js 提供
    if (adminNameSpan && currentUser && currentUser.username) {
        adminNameSpan.textContent = currentUser.username;
    } else if (adminNameSpan) {
        adminNameSpan.textContent = '管理员'; // 默认值
    }

    // 初始化时加载仪表盘统计数据
    loadDashboardStats();
    loadClassStudentCountChart();
    loadExamAverageScoreChart();

    const sidebarLinks = document.querySelectorAll('.sidebar .nav-link');
    const mainSections = document.querySelectorAll('.main-section');
    const sidebar = document.getElementById('adminSidebar');
    const sidebarCollapseButton = document.getElementById('sidebarCollapse');

    sidebarLinks.forEach(link => {
        link.addEventListener('click', function(event) {
            event.preventDefault();
            const targetId = this.getAttribute('data-target');

            if (this.id === 'logoutButton') {
                logout();
                return;
            }

            sidebarLinks.forEach(nav => nav.classList.remove('active'));
            this.classList.add('active');

            mainSections.forEach(section => {
                section.style.display = 'none';
            });

            if (targetId) {
                const targetSection = document.getElementById(targetId);
                if (targetSection) {
                    targetSection.style.display = 'block';
                    link.classList.add('active');

                    // 根据当前激活的区域加载数据
                    const targetId = targetSection.id;
                    console.log("Navigating to section:" + targetId);

                    if (targetId === 'dashboard-content') {
                        loadDashboardStats(); 
                        loadClassStudentCountChart(); 
                        loadExamAverageScoreChart(); 
                    } else if (targetId === 'exam-management-content') {
                        loadExams_backend();
                    } else if (targetId === 'student-management-content') {
                        populateClassDropdown(document.getElementById('class_id_form')); 
                        populateClassDropdown(document.getElementById('filterClassIdStudents'), true); 
                        loadStudents_backend(1); // 自动加载第一页学生数据
                    } else if (targetId === 'grade-management-content') {
                        loadGrades_backend(); 
                        
                        populateExamFilterDropdown('filterExamId', true); 
                        populateClassFilterDropdown('filterClassIdGrades', true); 

                        // Populate dropdowns for the grade modal (add/edit form)
                        populateExamDropdownForForm('grade_exam_id');   
                        
                        const gradeFilterForm = document.getElementById('gradeFilterForm');
                        if (gradeFilterForm) gradeFilterForm.reset();
                        const gradeStatsContainer = document.getElementById('gradeStatsContainer');
                        if (gradeStatsContainer) gradeStatsContainer.innerHTML = '';
                        // renderGradeTable(); // 这个是旧的mock渲染函数，已被loadGrades_backend替代
                    }
                }
            }
        });
    });

    // 4. 侧边栏切换 (针对小屏幕)
    if (sidebar && sidebarCollapseButton) {
        sidebarCollapseButton.addEventListener('click', function() {
            sidebar.classList.toggle('toggled');
        });
    }

    // 5. 默认激活仪表盘并加载对应内容
    const dashboardLink = document.querySelector('#adminSidebar .nav-link[data-target="dashboard-content"]');
    if (dashboardLink) {
        dashboardLink.click(); 
    } else { // Fallback if dashboard link isn't there, try to activate the first available link or class management
        const firstVisibleNavLink = document.querySelector('#adminSidebar .nav-link:not(#logoutButton)');
        if (firstVisibleNavLink) {
            firstVisibleNavLink.click(); // Activate the first link
        } else { // If nothing else, and class management exists, try to load it
             if (document.getElementById('class-management-content')) {
                loadClasses_backend();
             }
        }
    }
    
    // ===================================================================================
    // 班级管理模块事件绑定 (在 DOMContentLoaded 内)
    // ===================================================================================
    const addClassBtn_el_dom = document.getElementById('addClassBtn');
    const saveClassBtn_el_dom = document.getElementById('saveClassBtn');
    // const classForm_el_dom = document.getElementById('classForm'); // 已在 reset/validate 中使用

    if (addClassBtn_el_dom) {
        addClassBtn_el_dom.addEventListener('click', function() {
            resetClassForm_backend(); 
        });
    }

    if (saveClassBtn_el_dom) { // classForm_el_dom 检查已移至 validateClassForm_backend
        saveClassBtn_el_dom.addEventListener('click', async function() {
            if (!validateClassForm_backend()) {
                showAdminToast('请检查表单，确保所有必填项都已正确填写，且格式正确。', 'warning', '表单无效');
                return;
            }

            const hiddenClassIdInputEl_dom = document.getElementById('class_id');
            const classId = hiddenClassIdInputEl_dom ? hiddenClassIdInputEl_dom.value : null; 
            const className = document.getElementById('class_name').value.trim();
            const headTeacher = document.getElementById('head_teacher').value.trim();
            const studentCountStr = document.getElementById('student_count').value;
            const studentCount = studentCountStr.trim() === '' ? null : parseInt(studentCountStr, 10);

            const classData = {
                className: className,
                headTeacher: headTeacher,
                studentCount: studentCount 
            };

            const method = classId ? 'PUT' : 'POST';
            const endpoint = classId ? `/classes/${classId}` : '/classes';

            const originalButtonHTML = saveClassBtn_el_dom.innerHTML; 
            setButtonLoading(saveClassBtn_el_dom, true, '保存中...');

            try {
                await fetchApi(endpoint, method, classData); // 使用 fetchApi
                
                showAdminToast(classId ? '班级信息更新成功！' : '新班级添加成功！', 'success');
                $('#classModal').modal('hide');
                loadClasses_backend(); 

            } catch (error) {
                console.error('Error saving class specifically in saveClassBtn handler:', error);
                // fetchApi 会处理 401/403 及通用错误提示
                // 如果保存操作有特定错误需要UI反馈，可以在这里补充（但 fetchApi 的提示可能已足够）
                // 例如，处理来自 fetchApi 的 error.data 中的字段验证错误
                if (error.status === 400 && error.data && error.data.errors && Array.isArray(error.data.errors)) {
                     let messages = error.data.message || "保存操作失败";
                     messages += "\n" + error.data.errors.map(e => `字段 '${e.field}': ${e.defaultMessage}`).join("\n");
                     showAdminToast(messages, 'error', '保存错误 (校验)');
                } else if (!(error.message && error.message.startsWith('Authentication failed'))) {
                    // 如果不是认证错误（已由 fetchApi 处理），可以显示或记录其他错误
                    // showAdminToast(`保存班级操作失败: ${error.message}`, 'error'); // fetchApi 已显示
                }
            } finally {
                 setButtonLoading(saveClassBtn_el_dom, false, '', originalButtonHTML);
            }
        });
    }
    // ===================================================================================
    // END 班级管理事件绑定
    // ===================================================================================

    // (所有其他模块的mock数据填充和事件绑定逻辑保持不变，并放在这里)
    // ... (您的考试管理、学生管理、成绩管理的现有mock代码)
    // 确保所有 mock 数据的 renderTable, populateDropdowns 等函数调用在其对应的标签页激活逻辑中
    // 例如，考试管理的 renderExamTable() 应该在 exam-management-content 标签页被点击时调用

    // 示例: 旧的考试管理逻辑 (保持不变)
    // ---------- 考试管理模块代码开始 ----------
    const examTableBody = document.getElementById('examTableBody');
    const examModal = $('#examModal');
    const examForm = document.getElementById('examForm');
    const examModalLabel = document.getElementById('examModalLabel');
    const addExamBtn = document.getElementById('addExamBtn');
    const saveExamBtn = document.getElementById('saveExamBtn');
    const hiddenExamIdInput = document.getElementById('exam_id');

    function resetExamForm() {
        if (examForm) {
            examForm.reset();
            if (hiddenExamIdInput) hiddenExamIdInput.value = '';
            examForm.classList.remove('was-validated');
            $(examForm).find('.is-invalid').removeClass('is-invalid');
            $(examForm).find('.is-valid').removeClass('is-valid');
        }
        if (examModalLabel) examModalLabel.textContent = '新增考试';
    }

    function validateExamForm() {
        if (!examForm) return false;
        let isValid = true;
        
        $(examForm).find('.is-invalid').removeClass('is-invalid'); // 清除旧的验证状态

        // 示例校验：考试名称、科目、考试时间、地点不能为空
        const examName = document.getElementById('exam_name').value.trim();
        const subject = document.getElementById('subject').value.trim();
        const examTime = document.getElementById('exam_time').value;
        const location = document.getElementById('location').value.trim();

        if (!examName) {
            $('#exam_name').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#exam_name').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!subject) {
            $('#subject').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#subject').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!examTime) {
            $('#exam_time').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#exam_time').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }
        if (!location) {
            $('#location').addClass('is-invalid').siblings('.invalid-feedback').show();
            isValid = false;
        } else {
            $('#location').removeClass('is-invalid').addClass('is-valid').siblings('.invalid-feedback').hide();
        }

        // 使用HTML5内置验证
        if (!examForm.checkValidity()) {
            examForm.classList.add('was-validated');
            isValid = false;
        }
        return isValid;
    }

    async function loadExams_backend() {
        if (!examTableBody) {
            console.error("Exam table body not found!");
            return;
        }
        showTableLoadingSpinner(examTableBody, 9);
        try {
            const exams = await fetchApi('/exams');
            renderExamTable_backend(exams);
        } catch (error) {
            console.error('Error loading exams:', error);
            if (!(error.message && error.message.startsWith('Authentication failed'))) {
                examTableBody.innerHTML = `<tr><td colspan="9" class="text-center text-danger">加载考试数据时发生错误: ${error.message}</td></tr>`;
            }
        }
    }

    function renderExamTable_backend(exams) {
        if (!examTableBody) return;
        examTableBody.innerHTML = ''; 

        if (!exams || exams.length === 0) {
            examTableBody.innerHTML = '<tr><td colspan="9" class="text-center">暂无考试数据</td></tr>';
            return;
        }

        exams.forEach(exam => {
            const row = examTableBody.insertRow();
            row.innerHTML = `
                <td>${exam.id}</td>
                <td>${exam.examName || 'N/A'}</td>
                <td>${exam.subject || 'N/A'}</td>
                <td>${exam.examTime ? formatDateTime(exam.examTime) : 'N/A'}</td>
                <td>${exam.location || 'N/A'}</td>
                <td>${exam.description || 'N/A'}</td>
                <td>${exam.createTime ? formatDateTime(exam.createTime) : 'N/A'}</td>
                <td>${exam.updateTime ? formatDateTime(exam.updateTime) : 'N/A'}</td>
                <td class="action-buttons">
                    <button class="btn btn-sm btn-info edit-exam-btn" data-id="${exam.id}" title="编辑"><i class="fas fa-edit"></i> 编辑</button>
                    <button class="btn btn-sm btn-danger delete-exam-btn" data-id="${exam.id}" data-name="${exam.examName || '该考试'}" title="删除"><i class="fas fa-trash"></i> 删除</button>
                </td>
            `;
            row.querySelector('.edit-exam-btn').addEventListener('click', () => handleEditExamShowModal_backend(exam));
            const deleteBtn = row.querySelector('.delete-exam-btn');
            deleteBtn.addEventListener('click', (event) => handleDeleteExam_backend(exam.id, exam.examName || 'ID: '+exam.id, event.currentTarget));
        });
    }

    function handleEditExamShowModal_backend(examObj) { 
        resetExamForm();
        
        hiddenExamIdInput.value = examObj.id;
        document.getElementById('exam_name').value = examObj.examName || '';
        document.getElementById('subject').value = examObj.subject || '';
        // 后端返回的 examTime 可能是 LocalDateTime 对象，需要格式化为 datetime-local input 所需的格式
        // LocalDateTime.toString() 通常是 "YYYY-MM-DDTHH:mm:ss.sss" 格式，可以被 datetime-local input 直接使用
        // 如果有秒的小数部分，可能需要截断。简单起见，我们假设它可以直接用，或后端DTO已处理。
        document.getElementById('exam_time').value = examObj.examTime ? examObj.examTime.toString().substring(0, 16) : ''; // YYYY-MM-DDTHH:mm
        document.getElementById('location').value = examObj.location || '';
        document.getElementById('description').value = examObj.description || '';
        
        examModalLabel.textContent = '编辑考试';
        examModal.modal('show');
    }

    async function handleDeleteExam_backend(examId, examName, deleteButton) {
        if (!confirm(`确定要删除考试 "${examName}" 吗？此操作不可恢复。`)) {
            return;
        }
        
        const originalButtonHTML = deleteButton ? deleteButton.innerHTML : null;
        if(deleteButton) setButtonLoading(deleteButton, true, '', originalButtonHTML);

        try {
            await fetchApi(`/exams/${examId}`, 'DELETE');
            showAdminToast(`考试 "${examName}" 删除成功！`, 'success');
            loadExams_backend();
        } catch (error) {
            console.error('Failed to delete exam:', error);
            // fetchApi 会处理通用错误和认证错误
        } finally {
            if(deleteButton) setButtonLoading(deleteButton, false, '', originalButtonHTML);
        }
    }

    if (addExamBtn) {
        addExamBtn.addEventListener('click', function() {
            resetExamForm();
        });
    }

    if (saveExamBtn) {
        saveExamBtn.addEventListener('click', async function() {
            if (!validateExamForm()) {
                showAdminToast('请检查表单，确保所有必填项都已正确填写。', 'warning', '表单无效');
                return;
            }
            const examId = hiddenExamIdInput.value;
            const examData = {
                examName: document.getElementById('exam_name').value.trim(),
                subject: document.getElementById('subject').value.trim(),
                examTime: document.getElementById('exam_time').value, 
                location: document.getElementById('location').value.trim(),
                description: document.getElementById('description').value.trim()
            };
            const method = examId ? 'PUT' : 'POST';
            const endpoint = examId ? `/exams/${examId}` : '/exams';
            const originalButtonHTML = saveExamBtn.innerHTML;
            setButtonLoading(saveExamBtn, true, '保存中...');
            try {
                await fetchApi(endpoint, method, examData);
                showAdminToast(examId ? '考试信息更新成功！' : '新考试添加成功！', 'success');
                examModal.modal('hide');
                loadExams_backend();
            } catch (error) {
                console.error('Error saving exam:', error);
                // fetchApi 会处理通用错误和认证错误
                // 如果需要针对特定状态码（如400校验错误）做额外处理，可以在这里添加
                if (error.status === 400 && error.data && error.data.message) {
                     showAdminToast(`保存失败: ${error.data.message}`, 'error', '校验错误');
                }
            } finally {
                setButtonLoading(saveExamBtn, false, '', originalButtonHTML);
            }
        });
    }
    // ---------- 考试管理模块代码结束 ----------


    // (Similarly for Student and Grade management using MOCK data)
    // Make sure populateClassDropdown, populateStudentDropdown, populateExamDropdown used by
    // student and grade mock logic are defined or moved to global helpers if needed by backend versions later.


}); // End of DOMContentLoaded 

// 新增：加载各班级学生人数图表
let classStudentCountChartInstance = null; // 保存图表实例以便更新或销毁
async function loadClassStudentCountChart() {
    const canvasElement = document.getElementById('classStudentCountChart');
    if (!canvasElement) {
        console.error('Canvas for class student count chart not found!');
        return;
    }
    try {
        const response = await fetchApi('/dashboard/class-student-counts', 'GET');
        if (response && response.data && Array.isArray(response.data)) {
            const data = response.data;
            const labels = data.map(item => item.className);
            const studentCounts = data.map(item => item.studentCount);

            if (classStudentCountChartInstance) {
                classStudentCountChartInstance.destroy(); // 销毁旧实例以避免重叠
            }
            classStudentCountChartInstance = new Chart(canvasElement, {
                type: 'pie', // 或 'bar'
                data: {
                    labels: labels,
                    datasets: [{
                        label: '学生人数',
                        data: studentCounts,
                        backgroundColor: [
                            'rgba(255, 99, 132, 0.7)',
                            'rgba(54, 162, 235, 0.7)',
                            'rgba(255, 206, 86, 0.7)',
                            'rgba(75, 192, 192, 0.7)',
                            'rgba(153, 102, 255, 0.7)',
                            'rgba(255, 159, 64, 0.7)',
                            'rgba(199, 199, 199, 0.7)' // 添加更多颜色如果班级很多
                        ],
                        borderColor: [
                            'rgba(255, 99, 132, 1)',
                            'rgba(54, 162, 235, 1)',
                            'rgba(255, 206, 86, 1)',
                            'rgba(75, 192, 192, 1)',
                            'rgba(153, 102, 255, 1)',
                            'rgba(255, 159, 64, 1)',
                            'rgba(199, 199, 199, 1)'
                        ],
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            position: 'top',
                        },
                        title: {
                            display: false, // Card header 已经有标题了
                            text: '各班级学生人数分布'
                        }
                    }
                }
            });
        } else {
            console.error('Failed to load class student counts or data is not an array:', response);
            showAdminToast('加载班级学生数图表数据失败。', 'error');
        }
    } catch (error) {
        console.error('Error fetching class student counts for chart:', error);
        showAdminToast(`加载班级学生数图表时出错: ${error.message}`, 'error');
    }
}

// 新增：加载近期考试平均分趋势图表
let examAverageScoreChartInstance = null;
async function loadExamAverageScoreChart() {
    const canvasElement = document.getElementById('examAverageScoreChart');
    if (!canvasElement) {
        console.error('Canvas for exam average score chart not found!');
        return;
    }
    try {
        const response = await fetchApi('/dashboard/exam-average-scores', 'GET');
        if (response && response.data && Array.isArray(response.data)) {
            const data = response.data.sort((a, b) => new Date(a.examTime) - new Date(b.examTime)); // 按考试时间升序排序
            
            const labels = data.map(item => {
                const dateObj = new Date(item.examTime);
                const month = (dateObj.getMonth() + 1).toString().padStart(2, '0');
                const day = dateObj.getDate().toString().padStart(2, '0');
                const shortDate = `${month}/${day}`;
                return `${item.subject} - ${shortDate}`; // 例如: "数学 - 11/15"
            });
            const averageScores = data.map(item => item.averageScore !== null ? parseFloat(item.averageScore).toFixed(2) : null); // 处理null值

            if (examAverageScoreChartInstance) {
                examAverageScoreChartInstance.destroy();
            }
            examAverageScoreChartInstance = new Chart(canvasElement, {
                type: 'line',
                data: {
                    labels: labels,
                    datasets: [{
                        label: '平均分',
                        data: averageScores,
                        fill: false,
                        borderColor: 'rgb(75, 192, 192)',
                        tension: 0.1,
                        spanGaps: true // 连接null数据点之间的线
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: false, // 平均分不一定从0开始
                            suggestedMin: 50, // 可以根据实际情况调整
                            suggestedMax: 100
                        },
                        x: {
                            ticks: {
                                // autoSkip: true, // 自动跳过一些标签以避免拥挤
                                // maxRotation: 45, // 适度旋转标签
                                // minRotation: 30
                            }
                        }
                    },
                    plugins: {
                        legend: {
                            position: 'top',
                        },
                        title: {
                            display: false,
                            text: '近期考试平均分趋势'
                        },
                        tooltip: {
                            callbacks: {
                                title: function(tooltipItems) {
                                    // tooltipItems 是一个数组, 我们取第一个
                                    // 'data' 变量是上面定义的、已排序的考试数据数组
                                    const dataIndex = tooltipItems[0].dataIndex;
                                    const examData = data[dataIndex]; 
                                    return examData.examName; // 完整的考试名称作为标题
                                },
                                label: function(tooltipItem) {
                                    const dataIndex = tooltipItem.dataIndex;
                                    const examData = data[dataIndex];
                                    const score = examData.averageScore !== null ? parseFloat(examData.averageScore).toFixed(2) : 'N/A';
                                    const lines = [
                                        `科目: ${examData.subject}`,
                                        `平均分: ${score}`,
                                        `考试时间: ${formatDateTime(examData.examTime)}` // 使用全局的 formatDateTime
                                    ];
                                    return lines;
                                }
                            }
                        }
                    }
                }
            });
        } else {
            console.error('Failed to load exam average scores or data is not an array:', response);
            showAdminToast('加载考试平均分图表数据失败。', 'error');
        }
    } catch (error) {
        console.error('Error fetching exam average scores for chart:', error);
        showAdminToast(`加载考试平均分图表时出错: ${error.message}`, 'error');
    }
}